Set response Content-Type

This commit is contained in:
Anton Bachin 2021-04-19 00:36:48 +03:00
parent ea6e950bf5
commit 5df9963fff
64 changed files with 202 additions and 143 deletions

View File

@ -536,6 +536,34 @@ let respond_replacement = {|
</pre>
|}
let html_expected = {|<div class="spec value" id="val-html">
<a href="#val-html" class="anchor"></a><code><span><span class="keyword">val</span> html : <span>?status:<a href="#type-status">status</a> <span class="arrow">-&gt;</span></span> <span>?code:int <span class="arrow">-&gt;</span></span> <span>?headers:<span><span>(string * string)</span> list</span> <span class="arrow">-&gt;</span></span> <span>string <span class="arrow">-&gt;</span></span> <span><a href="#type-response">response</a> <a href="#type-promise">promise</a></span></span></code>
</div>
|}
let html_replacement = {|
<pre><span class="keyword">val</span> html :
<span class="optional">?status:<a href="#type-status">status</a> ->
?code:int ->
?headers:(string * string) list -></span>
string -> <a href="#type-response">response</a> <a href="#type-promise">promise</a>
</pre>
|}
let json_expected = {|<div class="spec value" id="val-json">
<a href="#val-json" class="anchor"></a><code><span><span class="keyword">val</span> json : <span>?status:<a href="#type-status">status</a> <span class="arrow">-&gt;</span></span> <span>?code:int <span class="arrow">-&gt;</span></span> <span>?headers:<span><span>(string * string)</span> list</span> <span class="arrow">-&gt;</span></span> <span>string <span class="arrow">-&gt;</span></span> <span><a href="#type-response">response</a> <a href="#type-promise">promise</a></span></span></code>
</div>
|}
let json_replacement = {|
<pre><span class="keyword">val</span> json :
<span class="optional">?status:<a href="#type-status">status</a> ->
?code:int ->
?headers:(string * string) list -></span>
string -> <a href="#type-response">response</a> <a href="#type-promise">promise</a>
</pre>
|}
let stream_expected = {|<div class="spec value" id="val-stream">
<a href="#val-stream" class="anchor"></a><code><span><span class="keyword">val</span> stream : <span>?status:<a href="#type-status">status</a> <span class="arrow">-&gt;</span></span> <span>?code:int <span class="arrow">-&gt;</span></span> <span>?headers:<span><span>(string * string)</span> list</span> <span class="arrow">-&gt;</span></span>
<span><span>(<span><a href="#type-response">response</a> <span class="arrow">-&gt;</span></span> <span>unit <a href="#type-promise">promise</a></span>)</span> <span class="arrow">-&gt;</span></span> <span><a href="#type-response">response</a> <a href="#type-promise">promise</a></span></span></code>
@ -1480,20 +1508,15 @@ let pretty_print_signatures soup =
Soup.replace (status $ "> table") (Soup.parse status_replacement);
Soup.add_class "multiline" status);
(* let method_ = soup $ "#type-method_" in
if_expected
method_expected
(fun () -> pretty_print method_)
(fun () ->
Soup.replace (method_ $ "> code") (Soup.parse method_replacement)); *)
(* let status = soup $ "#type-status" in
if_expected
status_expected
(fun () -> pretty_print status)
(fun () ->
Soup.replace (status $ "> code") (Soup.parse status_replacement);
Soup.add_class "multiline" status); *)
let multiline selector expected replacement =
let element = soup $ selector in
if_expected
expected
(fun () -> pretty_print element)
(fun () ->
Soup.replace (element $ "> code") (Soup.parse replacement);
Soup.add_class "multiline" element)
in
let response = soup $ "#val-response" in
if_expected
@ -1511,6 +1534,9 @@ let pretty_print_signatures soup =
Soup.replace (respond $ "> code") (Soup.parse respond_replacement);
Soup.add_class "multiline" respond);
multiline "#val-html" html_expected html_replacement;
multiline "#val-json" json_expected json_replacement;
let stream = soup $ "#val-stream" in
if_expected
stream_expected
@ -1536,16 +1562,6 @@ let pretty_print_signatures soup =
Soup.replace (element $ "> code") (Soup.parse replacement))
in
let multiline selector expected replacement =
let element = soup $ selector in
if_expected
expected
(fun () -> pretty_print element)
(fun () ->
Soup.replace (element $ "> code") (Soup.parse replacement);
Soup.add_class "multiline" element)
in
replace "#val-add_header" add_header_expected add_header_replacement;
multiline "#val-with_header" with_header_expected with_header_replacement;

View File

@ -44,7 +44,7 @@
@@ <span class="hljs-type">Dream</span>.logger
@@ <span class="hljs-type">Dream</span>.router <span class="hljs-string">[</span>
<span class="hljs-type">Dream</span>.get <span class="hljs-string">"/"</span> (<span class="keyword">fun</span> _ ->
<span class="hljs-type">Dream</span>.respond (hello <span class="hljs-string">"world"</span>));
<span class="hljs-type">Dream</span>.html (hello <span class="hljs-string">"world"</span>));
<span class="hljs-string">]</span>
@@ <span class="hljs-type">Dream</span>.not_found</pre>
@ -120,28 +120,6 @@
</div>
</header>
<!-- TODO Real getting started instructions link. -->
<!-- <header>
<p>
<span class="title">Dream</span> is a web framework ...
HTTP2, TLS, runs without a proxy, integration, scaling, GraphQL, etc.
</p>
<pre><code>let greet who =
&lt;html>&lt;body>&lt;h1>Hello, &lt;%s who %>!&lt;/h1>&lt;/body>&lt;/html>
let () =
Dream.run
@@ Dream.logger
@@ Dream.router [
Dream.get "/" @@ fun _request -> Dream.respond (greet "world");
]
@@ Dream.not_found
</code></pre>
</header> -->
<!-- Replaced by Soupault with postprocessed odoc output. -->
<div id="api"></div>

View File

@ -7,7 +7,7 @@ This project is so simple that it doesn't even log requests!
```ocaml
let () =
Dream.run (fun _ ->
Dream.respond "Good morning, world!")
Dream.html "Good morning, world!")
```
<br>

View File

@ -1,3 +1,3 @@
let () =
Dream.run (fun _ ->
Dream.respond "Good morning, world!")
Dream.html "Good morning, world!")

View File

@ -11,7 +11,7 @@ middlewares, the [*logger*](https://aantron.github.io/dream/#val-logger):
let () =
Dream.run
(Dream.logger (fun _ ->
Dream.respond "Good morning, world!"))
Dream.html "Good morning, world!"))
```
<br>
@ -27,7 +27,7 @@ in this example looks like this:
let () =
Dream.run
@@ Dream.logger
@@ fun _ -> Dream.respond "Good morning, world!"
@@ fun _ -> Dream.html "Good morning, world!"
```
<br>

View File

@ -1,4 +1,4 @@
let () =
Dream.run
@@ Dream.logger
@@ fun _ -> Dream.respond "Good morning, world!"
@@ fun _ -> Dream.html "Good morning, world!"

View File

@ -16,11 +16,11 @@ let () =
Dream.get "/"
(fun _ ->
Dream.respond "Good morning, world!");
Dream.html "Good morning, world!");
Dream.get "/echo/:word"
(fun request ->
Dream.respond (Dream.param "word" request));
Dream.html (Dream.param "word" request));
]
@@ Dream.not_found

View File

@ -5,11 +5,11 @@ let () =
Dream.get "/"
(fun _ ->
Dream.respond "Good morning, world!");
Dream.html "Good morning, world!");
Dream.get "/echo/:word"
(fun request ->
Dream.respond (Dream.param "word" request));
Dream.html (Dream.param "word" request));
]
@@ Dream.not_found

View File

@ -19,7 +19,7 @@ let () =
@@ count_requests
@@ Dream.router [
Dream.get "/" (fun _ ->
Dream.respond (Printf.sprintf "Saw %i request(s)!" !count));
Dream.html (Printf.sprintf "Saw %i request(s)!" !count));
]
@@ Dream.not_found
```

View File

@ -10,6 +10,6 @@ let () =
@@ count_requests
@@ Dream.router [
Dream.get "/" (fun _ ->
Dream.respond (Printf.sprintf "Saw %i request(s)!" !count));
Dream.html (Printf.sprintf "Saw %i request(s)!" !count));
]
@@ Dream.not_found

View File

@ -33,7 +33,7 @@ let () =
raise (Failure "The Web app failed!"));
Dream.get "/" (fun _ ->
Dream.respond (Printf.sprintf
Dream.html (Printf.sprintf
"%3i request(s) successful\n%3i request(s) failed"
!successful !failed));

View File

@ -22,7 +22,7 @@ let () =
raise (Failure "The Web app failed!"));
Dream.get "/" (fun _ ->
Dream.respond (Printf.sprintf
Dream.html (Printf.sprintf
"%3i request(s) successful\n%3i request(s) failed"
!successful !failed));

View File

@ -10,9 +10,13 @@ let () =
Dream.run
@@ Dream.logger
@@ Dream.router [
Dream.post "/echo" (fun request ->
let%lwt body = Dream.body request in
Dream.respond body);
Dream.respond
~headers:["Content-Type", "application/octet-stream"]
body);
]
@@ Dream.not_found
```

View File

@ -2,8 +2,12 @@ let () =
Dream.run
@@ Dream.logger
@@ Dream.router [
Dream.post "/echo" (fun request ->
let%lwt body = Dream.body request in
Dream.respond body);
Dream.respond
~headers:["Content-Type", "application/octet-stream"]
body);
]
@@ Dream.not_found

View File

@ -25,7 +25,7 @@ let () =
(fun request ->
Dream.param "word" request
|> render
|> Dream.respond);
|> Dream.html);
]
@@ Dream.not_found

View File

@ -14,7 +14,7 @@ let () =
(fun request ->
Dream.param "word" request
|> render
|> Dream.respond);
|> Dream.html);
]
@@ Dream.not_found

View File

@ -16,6 +16,7 @@ let my_error_template debug_info suggested_response =
and reason = Dream.status_to_string status in
suggested_response
|> Dream.with_header "Content-Type" Dream.text_html
|> Dream.with_body begin
<html>
<body>

View File

@ -4,6 +4,7 @@ let my_error_template debug_info suggested_response =
and reason = Dream.status_to_string status in
suggested_response
|> Dream.with_header "Content-Type" Dream.text_html
|> Dream.with_body begin
<html>
<body>

View File

@ -14,7 +14,7 @@ let () =
Dream.get "/"
(fun request ->
Dream.log "Sending greeting to %s!" (Dream.client request);
Dream.respond "Good morning, world!");
Dream.html "Good morning, world!");
Dream.get "/fail"
(fun _ ->

View File

@ -6,7 +6,7 @@ let () =
Dream.get "/"
(fun request ->
Dream.log "Sending greeting to %s!" (Dream.client request);
Dream.respond "Good morning, world!");
Dream.html "Good morning, world!");
Dream.get "/fail"
(fun _ ->

View File

@ -15,11 +15,11 @@ let () =
| None ->
let%lwt () = Dream.invalidate_session request in
let%lwt () = Dream.put_session "user" "alice" request in
Dream.respond "You weren't logged in; but now you are!"
Dream.html "You weren't logged in; but now you are!"
| Some username ->
Printf.ksprintf
Dream.respond "Welcome back, %s!" (Dream.html_escape username)
Dream.html "Welcome back, %s!" (Dream.html_escape username)
```
<pre><code><b>$ dune exec --root . ./session.exe</b></code></pre>

View File

@ -8,8 +8,8 @@ let () =
| None ->
let%lwt () = Dream.invalidate_session request in
let%lwt () = Dream.put_session "user" "alice" request in
Dream.respond "You weren't logged in; but now you are!"
Dream.html "You weren't logged in; but now you are!"
| Some username ->
Printf.ksprintf
Dream.respond "Welcome back, %s!" (Dream.html_escape username)
Dream.html "Welcome back, %s!" (Dream.html_escape username)

View File

@ -13,10 +13,11 @@ let () =
match Dream.cookie "ui.language" request with
| Some value ->
Printf.ksprintf
Dream.respond "Your preferred language is %s!" (Dream.html_escape value)
Dream.html "Your preferred language is %s!" (Dream.html_escape value)
| None ->
Dream.response "Set language preference; come again!"
|> Dream.add_header "Content-Type" Dream.text_html
|> Dream.set_cookie "ui.language" "ut-OP" request
|> Lwt.return
```

View File

@ -6,9 +6,10 @@ let () =
match Dream.cookie "ui.language" request with
| Some value ->
Printf.ksprintf
Dream.respond "Your preferred language is %s!" (Dream.html_escape value)
Dream.html "Your preferred language is %s!" (Dream.html_escape value)
| None ->
Dream.response "Set language preference; come again!"
|> Dream.add_header "Content-Type" Dream.text_html
|> Dream.set_cookie "ui.language" "ut-OP" request
|> Lwt.return

View File

@ -31,13 +31,13 @@ let () =
Dream.get "/"
(fun request ->
Dream.respond (show_form request));
Dream.html (show_form request));
Dream.post "/"
(fun request ->
match%lwt Dream.form request with
| `Ok ["message", message] ->
Dream.respond (show_form ~message request)
Dream.html (show_form ~message request)
| _ ->
Dream.empty `Bad_Request);

View File

@ -23,13 +23,13 @@ let () =
Dream.get "/"
(fun request ->
Dream.respond (show_form request));
Dream.html (show_form request));
Dream.post "/"
(fun request ->
match%lwt Dream.form request with
| `Ok ["message", message] ->
Dream.respond (show_form ~message request)
Dream.html (show_form ~message request)
| _ ->
Dream.empty `Bad_Request);

View File

@ -12,17 +12,13 @@ It can also be greatly simplified with
```ocaml
let to_json request =
match Dream.header "Content-Type" request with
| Some "application/json" ->
let%lwt body = Dream.body request in
begin match Yojson.Basic.from_string body with
| exception _ -> Lwt.return None
| json -> Lwt.return (Some json)
end
| _ -> Lwt.return None
let () =
@ -45,7 +41,7 @@ let () =
`String message
|> Yojson.Basic.to_string
|> Dream.respond ~headers:["Content-Type", "application/json"]);
|> Dream.json);
]
@@ Dream.not_found

View File

@ -1,15 +1,11 @@
let to_json request =
match Dream.header "Content-Type" request with
| Some "application/json" ->
let%lwt body = Dream.body request in
begin match Yojson.Basic.from_string body with
| exception _ -> Lwt.return None
| json -> Lwt.return (Some json)
end
| _ -> Lwt.return None
let () =
@ -32,7 +28,7 @@ let () =
`String message
|> Yojson.Basic.to_string
|> Dream.respond ~headers:["Content-Type", "application/json"]);
|> Dream.json);
]
@@ Dream.not_found

View File

@ -34,11 +34,11 @@ let () =
@@ Dream.router [
Dream.get "/" (fun request ->
Dream.respond (home request));
Dream.html (home request));
Dream.post "/" (fun request ->
match%lwt Dream.multipart request with
| `Ok ["files", `Files files] -> Dream.respond (report files)
| `Ok ["files", `Files files] -> Dream.html (report files)
| _ -> Dream.empty `Bad_Request);
]

View File

@ -24,11 +24,11 @@ let () =
@@ Dream.router [
Dream.get "/" (fun request ->
Dream.respond (home request));
Dream.html (home request));
Dream.post "/" (fun request ->
match%lwt Dream.multipart request with
| `Ok ["files", `Files files] -> Dream.respond (report files)
| `Ok ["files", `Files files] -> Dream.html (report files)
| _ -> Dream.empty `Bad_Request);
]

View File

@ -48,14 +48,14 @@ let () =
Dream.get "/" (fun request ->
let%lwt comments = Dream.sql list_comments request in
Dream.respond (render comments request));
Dream.html (render comments request));
Dream.post "/" (fun request ->
match%lwt Dream.form request with
| `Ok ["text", text] ->
let%lwt () = Dream.sql (add_comment text) request in
let%lwt comments = Dream.sql list_comments request in
Dream.respond (render comments request)
Dream.html (render comments request)
| _ ->
Dream.empty `Bad_Request);

View File

@ -41,14 +41,14 @@ let () =
Dream.get "/" (fun request ->
let%lwt comments = Dream.sql list_comments request in
Dream.respond (render comments request));
Dream.html (render comments request));
Dream.post "/" (fun request ->
match%lwt Dream.form request with
| `Ok ["text", text] ->
let%lwt () = Dream.sql (add_comment text) request in
let%lwt comments = Dream.sql list_comments request in
Dream.respond (render comments request)
Dream.html (render comments request)
| _ ->
Dream.empty `Bad_Request);

View File

@ -23,8 +23,12 @@ let () =
Dream.run
@@ Dream.logger
@@ Dream.router [
Dream.post "/echo" (fun request ->
Dream.stream (echo request));
Dream.stream
~headers:["Content-Type", "application/octet-stream"]
(echo request));
]
@@ Dream.not_found
```

View File

@ -14,7 +14,11 @@ let () =
Dream.run
@@ Dream.logger
@@ Dream.router [
Dream.post "/echo" (fun request ->
Dream.stream (echo request));
Dream.stream
~headers:["Content-Type", "application/octet-stream"]
(echo request));
]
@@ Dream.not_found

View File

@ -34,7 +34,7 @@ let () =
Dream.get "/"
(fun _ ->
Dream.respond home);
Dream.html home);
Dream.get "/websocket"
(fun _ ->

View File

@ -24,7 +24,7 @@ let () =
Dream.get "/"
(fun _ ->
Dream.respond home);
Dream.html home);
Dream.get "/websocket"
(fun _ ->

View File

@ -9,7 +9,7 @@ Enabling HTTPS in Dream is very easy: just pass `~https:true` to
let () =
Dream.run ~https:true
@@ Dream.logger
@@ fun _ -> Dream.respond "Good morning, world!"
@@ fun _ -> Dream.html "Good morning, world!"
```
<pre><code><b>$ dune exec --root . ./https.exe</b></code></pre>

View File

@ -1,4 +1,4 @@
let () =
Dream.run ~https:true
@@ Dream.logger
@@ fun _ -> Dream.respond "Good morning, world!"
@@ fun _ -> Dream.html "Good morning, world!"

View File

@ -32,7 +32,7 @@ let () =
@@ Dream.router([
Dream.get("/",
(_ => Dream.respond(home))),
(_ => Dream.html(home))),
Dream.get("/static/**",
Dream.static("./static")),

View File

@ -13,7 +13,7 @@ let () =
@@ Dream.router([
Dream.get("/",
(_ => Dream.respond(home))),
(_ => Dream.html(home))),
Dream.get("/static/**",
Dream.static("./static")),

View File

@ -7,7 +7,7 @@ This example shows the simplest Dream program one could write:
```reason
let () =
Dream.run(_ =>
Dream.respond("Good morning, reasonable world!"));
Dream.html("Good morning, reasonable world!"));
```
<pre><code><b>$ dune exec --root . ./hello.exe</b>

View File

@ -1,3 +1,3 @@
let () =
Dream.run(_ =>
Dream.respond("Good morning, reasonable world!"));
Dream.html("Good morning, reasonable world!"));

View File

@ -29,7 +29,7 @@ let render = response => {
let () =
Dream.run
@@ Dream.logger
@@ _ => Dream.stream(render);
@@ _ => Dream.stream(~headers=[("Content-Type", Dream.text_html)], render);
```
<pre><code><b>$ dune exec --root . ./template-stream.exe</b></code></pre>

View File

@ -21,4 +21,4 @@ let render = response => {
let () =
Dream.run
@@ Dream.logger
@@ _ => Dream.stream(render);
@@ _ => Dream.stream(~headers=[("Content-Type", Dream.text_html)], render);

View File

@ -24,7 +24,7 @@ let () =
(request =>
Dream.param("word", request)
|> render
|> Dream.respond)),
|> Dream.html)),
])
@@ Dream.not_found;

View File

@ -15,7 +15,7 @@ let () =
(request =>
Dream.param("word", request)
|> render
|> Dream.respond)),
|> Dream.html)),
])
@@ Dream.not_found;

View File

@ -31,7 +31,7 @@ let () =
@@ Dream.router [
Dream.get "/"
(fun _ -> Dream.respond home);
(fun _ -> Dream.html home);
Dream.get "/static/**"
(Dream.static "./static");

View File

@ -12,7 +12,7 @@ let () =
@@ Dream.router [
Dream.get "/"
(fun _ -> Dream.respond home);
(fun _ -> Dream.html home);
Dream.get "/static/**"
(Dream.static "./static");

View File

@ -33,7 +33,7 @@ let () =
@@ Dream.router [
Dream.get "/"
(fun _ -> Dream.respond home);
(fun _ -> Dream.html home);
Dream.get "/static/**"
(Dream.static "./static");

View File

@ -12,7 +12,7 @@ let () =
@@ Dream.router [
Dream.get "/"
(fun _ -> Dream.respond home);
(fun _ -> Dream.html home);
Dream.get "/static/**"
(Dream.static "./static");

View File

@ -58,7 +58,7 @@ let () =
@@ Dream.logger
@@ Dream.router [
Dream.get "/" (fun _ -> Dream.respond home);
Dream.get "/" (fun _ -> Dream.html home);
Dream.get "/poll" (fun _ ->
match !server_state with
@ -67,11 +67,11 @@ let () =
| Messages_accumulating [] ->
let response_promise, respond = Lwt.wait () in
server_state := Client_waiting (fun message ->
Lwt.wakeup_later respond (Dream.response message));
Lwt.wakeup_later respond (Dream.html message));
response_promise
| Messages_accumulating messages ->
server_state := Messages_accumulating [];
Dream.respond (String.concat "\n" (List.rev messages)));
Dream.html (String.concat "\n" (List.rev messages)));
]
@@ Dream.not_found

View File

@ -10,9 +10,9 @@ let () =
Dream.run (fun request ->
match Dream.query "echo" request with
| None ->
Dream.respond "Use ?echo=foo to give a message to echo!"
Dream.html "Use ?echo=foo to give a message to echo!"
| Some message ->
Dream.respond (Dream.html_escape message))
Dream.html (Dream.html_escape message))
```
<pre><code><b>$ dune exec --root . ./query.exe</b></code></pre>

View File

@ -2,6 +2,6 @@ let () =
Dream.run (fun request ->
match Dream.query "echo" request with
| None ->
Dream.respond "Use ?echo=foo to give a message to echo!"
Dream.html "Use ?echo=foo to give a message to echo!"
| Some message ->
Dream.respond (Dream.html_escape message))
Dream.html (Dream.html_escape message))

View File

@ -69,7 +69,7 @@ let () =
@@ Dream.logger
@@ Dream.router [
Dream.get "/" (fun _ -> Dream.respond home);
Dream.get "/" (fun _ -> Dream.html home);
Dream.get "/push" (fun _ ->
Dream.stream

View File

@ -20,4 +20,4 @@ let render response =
let () =
Dream.run
@@ Dream.logger
@@ fun _ -> Dream.stream render
@@ fun _ -> Dream.stream ~headers:["Content-Type", Dream.text_html] render

View File

@ -31,7 +31,7 @@ let () =
(fun request ->
render (Dream.param "word" request)
|> html_to_string
|> Dream.respond);
|> Dream.html);
]
@@ Dream.not_found

View File

@ -20,7 +20,7 @@ let () =
(fun request ->
render (Dream.param "word" request)
|> html_to_string
|> Dream.respond);
|> Dream.html);
]
@@ Dream.not_found

View File

@ -31,7 +31,7 @@ and handler = request -> response promise
{[
let () =
Dream.run (fun _ ->
Dream.respond "Good morning, world!")
Dream.html "Good morning, world!")
]} *)
and middleware = handler -> handler
@ -44,7 +44,7 @@ and middleware = handler -> handler
let () =
Dream.run
@@ Dream.logger
@@ fun _ -> Dream.respond "Good morning, world!"
@@ fun _ -> Dream.html "Good morning, world!"
]}
Examples
@ -389,7 +389,14 @@ val response :
string -> response
(** Creates a new {!type-response} with the given string as body. [~code] and
[~status] are two ways to specify the {!type-status} code, which is [200 OK]
by default. The headers are empty by default. *)
by default. The headers are empty by default.
Note that browsers may interpret lack of a [Content-Type:] header as if its
value were [application/octet-stream] or [text/html; charset=us-ascii],
which will prevent correct interpretation of UTF-8 strings. Either add a
[Content-Type:] header using [~headers] or {!Dream.add_header}, or use a
wrapper like {!Dream.html}. The modern [Content-Type:] for HTML is
[text/html; charset=utf-8]. See {!Dream.text_html}. *)
val respond :
?status:status ->
@ -399,6 +406,23 @@ val respond :
(** Same as {!Dream.val-response}, but the new {!type-response} is wrapped in a
{!type-promise}. *)
val html :
?status:status ->
?code:int ->
?headers:(string * string) list ->
string -> response promise
(** Same as {!Dream.respond}, but adds [Content-Type: text/html; charset=utf-8]
if [Content-Type:] is absent from [~headers]. See {!Dream.text_html}. *)
val json :
?status:status ->
?code:int ->
?headers:(string * string) list ->
string -> response promise
(** Same as {!Dream.respond}, but adds [Content-Type: application/json] if
[Content-Type:] is absent from [~headers]. See
{!Dream.application_json}. *)
val empty :
?headers:(string * string) list ->
status -> response promise
@ -718,7 +742,7 @@ val origin_referer_check : middleware
{[
match%lwt Dream.form request with
| `Ok ["my.field", value] -> (* ... *)
| _ -> Dream.respond `Bad_Request
| _ -> Dream.empty `Bad_Request
]}
See example
@ -1056,7 +1080,7 @@ val router : route list -> middleware
Dream.run
@@ Dream.router [
Dream.get "/echo/:word" @@ fun request ->
Dream.respond (Dream.param "word" request);
Dream.html (Dream.param "word" request);
]
@@ Dream.not_found
]}
@ -1970,6 +1994,12 @@ val drop_trailing_slash : string list -> string list
checking if the last element in the list is [""], and, if it is, dropping
it. *)
val text_html : string
(** The string ["text/html; charset=utf-8"] for [Content-Type:] headers. *)
val application_json : string
(** The string ["application/json"] for [Content-Type:] headers. *)
(** {1 Cryptography} *)

View File

@ -294,16 +294,16 @@ let graphql make_context schema = fun request ->
begin match%lwt run_query make_context schema request json with
| Error json ->
Yojson.Basic.to_string json
|> Dream.respond ~headers:["Content-Type", "application/json"]
|> Dream.json
| Ok (`Response json) ->
Yojson.Basic.to_string json
|> Dream.respond ~headers:["Content-Type", "application/json"]
|> Dream.json
| Ok (`Stream _) ->
make_error "Subscriptions and streaming should use WebSocket transport"
|> Yojson.Basic.to_string
|> Dream.respond ~headers:["Content-Type", "application/json"]
|> Dream.json
end
| _ ->
@ -339,4 +339,4 @@ let graphiql graphql_endpoint =
in
fun _request ->
Dream.respond (Lazy.force html)
Dream.html (Lazy.force html)

View File

@ -237,7 +237,7 @@ let respond_with_option f =
| Some response -> response
| None -> Dream.response ~status:`Internal_Server_Error ""))
(fun () ->
Dream.respond ~status:`Internal_Server_Error "")
Dream.empty `Internal_Server_Error)

View File

@ -36,7 +36,7 @@ let chop_site_prefix prefix =
fun next_handler request ->
match match_site_prefix prefix (Dream.path request) with
| None ->
Dream.respond ~status:`Bad_Gateway ""
Dream.empty `Bad_Gateway
| Some path ->
request
|> Dream.with_prefix prefix_reversed

View File

@ -21,7 +21,7 @@ let default_loader local_root path _ =
Lwt_io.(with_file ~mode:Input file)(fun channel ->
Lwt_io.read channel
|> Lwt.map Dream.response))
(fun _exn -> Dream.respond ~status:`Not_Found "")
(fun _exn -> Dream.empty `Not_Found)
(* TODO Add ETag handling. *)
(* TODO Add automatic Content-Type handling. *)
@ -63,11 +63,11 @@ let validate_path request =
let static ?(loader = default_loader) local_root = fun request ->
if not @@ Dream.methods_equal (Dream.method_ request) `GET then
Dream.respond ~status:`Method_Not_Allowed ""
Dream.empty `Not_Found
else
match validate_path request with
| None -> Dream.respond ~status:`Not_Found ""
| None -> Dream.empty `Not_Found
| Some path ->
let%lwt response = loader local_root path request in

View File

@ -216,3 +216,11 @@ let rec drop_trailing_slash = function
function. *)
let make_path path =
"/" ^ (String.concat "/" path)
let text_html =
"text/html; charset=utf-8"
let application_json =
"application/json"

View File

@ -471,15 +471,30 @@ let response
response
let respond
?status
?code
?headers
body =
let respond ?status ?code ?headers body =
response ?status ?code ?headers body
|> Lwt.return
let html ?status ?code ?headers body =
let response = response ?status ?code ?headers body in
let response =
if has_header "Content-Type" response then
response
else
add_header "Content-Type" Formats.text_html response
in
Lwt.return response
let json ?status ?code ?headers body =
let response = response ?status ?code ?headers body in
let response =
if has_header "Content-Type" response then
response
else
add_header "Content-Type" Formats.application_json response
in
Lwt.return response
let stream ?status ?code ?headers f =
let response =
response ?status ?code ?headers ""