tiny_httpd/tiny_httpd/Tiny_httpd/index.html
2024-02-23 03:22:55 +00:00

103 lines
38 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Tiny_httpd (tiny_httpd.Tiny_httpd)</title><meta charset="utf-8"/><link rel="stylesheet" href="../../_odoc-theme/odoc.css"/><meta name="generator" content="odoc 2.4.1"/><meta name="viewport" content="width=device-width,initial-scale=1.0"/><script src="../../highlight.pack.js"></script><script>hljs.initHighlightingOnLoad();</script></head><body class="odoc"><nav class="odoc-nav"><a href="../index.html">Up</a> <a href="../index.html">tiny_httpd</a> &#x00BB; Tiny_httpd</nav><header class="odoc-preamble"><h1>Module <code><span>Tiny_httpd</span></code></h1><p>Tiny Http Server</p><p>This library implements a very simple, basic HTTP/1.1 server using blocking IOs and threads. Basic routing based is provided for convenience, so that several handlers can be registered.</p><p>It is possible to use a thread pool, see <a href="#val-create"><code>create</code></a>'s argument <code>new_thread</code>.</p><p>The <code>echo</code> example (see <code>src/examples/echo.ml</code>) demonstrates some of the features by declaring a few endpoints, including one for uploading files:</p><pre class="language-ocaml"><code>module S = Tiny_httpd
let () =
let server = S.create () in
(* say hello *)
S.add_route_handler ~meth:`GET server
S.Route.(exact &quot;hello&quot; @/ string @/ return)
(fun name _req -&gt; S.Response.make_string (Ok (&quot;hello &quot; ^name ^&quot;!\n&quot;)));
(* echo request *)
S.add_route_handler server
S.Route.(exact &quot;echo&quot; @/ return)
(fun req -&gt; S.Response.make_string
(Ok (Format.asprintf &quot;echo:@ %a@.&quot; S.Request.pp req)));
(* file upload *)
S.add_route_handler ~meth:`PUT server
S.Route.(exact &quot;upload&quot; @/ string_urlencoded @/ return)
(fun path req -&gt;
try
let oc = open_out @@ &quot;/tmp/&quot; ^ path in
output_string oc req.S.Request.body;
flush oc;
S.Response.make_string (Ok &quot;uploaded file&quot;)
with e -&gt;
S.Response.fail ~code:500 &quot;couldn't upload file: %s&quot;
(Printexc.to_string e)
);
(* run the server *)
Printf.printf &quot;listening on http://%s:%d\n%!&quot; (S.addr server) (S.port server);
match S.run server with
| Ok () -&gt; ()
| Error e -&gt; raise e</code></pre><p>It is then possible to query it using curl:</p><pre class="language-ocaml"><code>$ dune exec src/examples/echo.exe &amp;
listening on http://127.0.0.1:8080
# the path &quot;hello/name&quot; greets you.
$ curl -X GET http://localhost:8080/hello/quadrarotaphile
hello quadrarotaphile!
# the path &quot;echo&quot; just prints the request.
$ curl -X GET http://localhost:8080/echo --data &quot;howdy y'all&quot;
echo:
{meth=GET;
headers=Host: localhost:8080
User-Agent: curl/7.66.0
Accept: */*
Content-Length: 10
Content-Type: application/x-www-form-urlencoded;
path=&quot;/echo&quot;; body=&quot;howdy y'all&quot;}</code></pre></header><nav class="odoc-toc"><ul><li><a href="#tiny-buffer-implementation">Tiny buffer implementation</a></li><li><a href="#generic-byte-streams">Generic byte streams</a></li><li><a href="#io-abstraction">IO Abstraction</a></li><li><a href="#logging">Logging</a></li><li><a href="#main-server-type">Main Server Type</a><ul><li><a href="#http-methods">HTTP Methods</a></li><li><a href="#headers">Headers</a></li><li><a href="#requests">Requests</a></li><li><a href="#response-codes">Response Codes</a></li><li><a href="#responses">Responses</a></li><li><a href="#routing">Routing</a></li><li><a href="#middlewares">Middlewares</a></li><li><a href="#main-server-type_2">Main Server type</a></li><li><a href="#request-handlers">Request handlers</a></li><li><a href="#server-sent-events">Server-sent events</a></li><li><a href="#upgrade-handlers">Upgrade handlers</a></li><li><a href="#run-the-server">Run the server</a></li></ul></li><li><a href="#utils">Utils</a></li><li><a href="#resource-pool">Resource pool</a></li><li><a href="#static-directory-serving">Static directory serving</a></li></ul></nav><div class="odoc-content"><h3 id="tiny-buffer-implementation"><a href="#tiny-buffer-implementation" class="anchor"></a>Tiny buffer implementation</h3><p>These buffers are used to avoid allocating too many byte arrays when processing streams and parsing requests.</p><div class="odoc-spec"><div class="spec module anchored" id="module-Buf"><a href="#module-Buf" class="anchor"></a><code><span><span class="keyword">module</span> Buf</span><span> = <a href="../Tiny_httpd_buf/index.html">Tiny_httpd_buf</a></span></code></div></div><h3 id="generic-byte-streams"><a href="#generic-byte-streams" class="anchor"></a>Generic byte streams</h3><div class="odoc-spec"><div class="spec module anchored" id="module-Byte_stream"><a href="#module-Byte_stream" class="anchor"></a><code><span><span class="keyword">module</span> Byte_stream</span><span> = <a href="../Tiny_httpd_stream/index.html">Tiny_httpd_stream</a></span></code></div></div><h3 id="io-abstraction"><a href="#io-abstraction" class="anchor"></a>IO Abstraction</h3><div class="odoc-spec"><div class="spec module anchored" id="module-IO"><a href="#module-IO" class="anchor"></a><code><span><span class="keyword">module</span> IO</span><span> = <a href="../Tiny_httpd_io/index.html">Tiny_httpd_io</a></span></code></div></div><h3 id="logging"><a href="#logging" class="anchor"></a>Logging</h3><div class="odoc-spec"><div class="spec module anchored" id="module-Log"><a href="#module-Log" class="anchor"></a><code><span><span class="keyword">module</span> Log</span><span> = <a href="../Tiny_httpd_log/index.html">Tiny_httpd_log</a></span></code></div></div><h3 id="main-server-type"><a href="#main-server-type" class="anchor"></a>Main Server Type</h3><div class="odoc-spec"><div class="spec type anchored" id="type-buf"><a href="#type-buf" class="anchor"></a><code><span><span class="keyword">type</span> buf</span><span> = <a href="../Tiny_httpd_buf/index.html#type-t">Tiny_httpd_buf.t</a></span></code></div></div><div class="odoc-spec"><div class="spec type anchored" id="type-byte_stream"><a href="#type-byte_stream" class="anchor"></a><code><span><span class="keyword">type</span> byte_stream</span><span> = <a href="../Tiny_httpd_stream/index.html#type-t">Tiny_httpd_stream.t</a></span></code></div></div><h5 id="http-methods"><a href="#http-methods" class="anchor"></a>HTTP Methods</h5><div class="odoc-spec"><div class="spec module anchored" id="module-Meth"><a href="#module-Meth" class="anchor"></a><code><span><span class="keyword">module</span> Meth</span><span> = <a href="../Tiny_httpd_server/Meth/index.html">Tiny_httpd_server.Meth</a></span></code></div></div><h5 id="headers"><a href="#headers" class="anchor"></a>Headers</h5><p>Headers are metadata associated with a request or response.</p><div class="odoc-spec"><div class="spec module anchored" id="module-Headers"><a href="#module-Headers" class="anchor"></a><code><span><span class="keyword">module</span> Headers</span><span> = <a href="../Tiny_httpd_server/Headers/index.html">Tiny_httpd_server.Headers</a></span></code></div></div><h5 id="requests"><a href="#requests" class="anchor"></a>Requests</h5><p>Requests are sent by a client, e.g. a web browser or cURL. From the point of view of the server, they're inputs.</p><div class="odoc-spec"><div class="spec module anchored" id="module-Request"><a href="#module-Request" class="anchor"></a><code><span><span class="keyword">module</span> Request</span><span> = <a href="../Tiny_httpd_server/Request/index.html">Tiny_httpd_server.Request</a></span></code></div></div><h5 id="response-codes"><a href="#response-codes" class="anchor"></a>Response Codes</h5><div class="odoc-spec"><div class="spec module anchored" id="module-Response_code"><a href="#module-Response_code" class="anchor"></a><code><span><span class="keyword">module</span> Response_code</span><span> = <a href="../Tiny_httpd_server/Response_code/index.html">Tiny_httpd_server.Response_code</a></span></code></div></div><h5 id="responses"><a href="#responses" class="anchor"></a>Responses</h5><p>Responses are what a http server, such as <a href="#"><code>Tiny_httpd</code></a>, send back to the client to answer a <a href="../Tiny_httpd_server/Request/index.html#type-t"><code>Request.t</code></a></p><div class="odoc-spec"><div class="spec module anchored" id="module-Response"><a href="#module-Response" class="anchor"></a><code><span><span class="keyword">module</span> Response</span><span> = <a href="../Tiny_httpd_server/Response/index.html">Tiny_httpd_server.Response</a></span></code></div></div><h5 id="routing"><a href="#routing" class="anchor"></a>Routing</h5><p>Basic type-safe routing of handlers based on URL paths. This is optional, it is possible to only define the root handler with something like <a href="https://github.com/anuragsoni/routes/">Routes</a>.</p><ul class="at-tags"><li class="since"><span class="at-tag">since</span> 0.6</li></ul><div class="odoc-spec"><div class="spec module anchored" id="module-Route"><a href="#module-Route" class="anchor"></a><code><span><span class="keyword">module</span> Route</span><span> = <a href="../Tiny_httpd_server/Route/index.html">Tiny_httpd_server.Route</a></span></code></div></div><h5 id="middlewares"><a href="#middlewares" class="anchor"></a>Middlewares</h5><p>A middleware can be inserted in a handler to modify or observe its behavior.</p><ul class="at-tags"><li class="since"><span class="at-tag">since</span> 0.11</li></ul><div class="odoc-spec"><div class="spec module anchored" id="module-Middleware"><a href="#module-Middleware" class="anchor"></a><code><span><span class="keyword">module</span> Middleware</span><span> = <a href="../Tiny_httpd_server/Middleware/index.html">Tiny_httpd_server.Middleware</a></span></code></div></div><h5 id="main-server-type_2"><a href="#main-server-type_2" class="anchor"></a>Main Server type</h5><div class="odoc-spec"><div class="spec type anchored" id="type-t"><a href="#type-t" class="anchor"></a><code><span><span class="keyword">type</span> t</span><span> = <a href="../Tiny_httpd_server/index.html#type-t">Tiny_httpd_server.t</a></span></code></div><div class="spec-doc"><p>A HTTP server. See <a href="#val-create"><code>create</code></a> for more details.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-create"><a href="#val-create" class="anchor"></a><code><span><span class="keyword">val</span> create :
<span><span class="optlabel">?masksigpipe</span>:bool <span class="arrow">&#45;&gt;</span></span>
<span><span class="optlabel">?max_connections</span>:int <span class="arrow">&#45;&gt;</span></span>
<span><span class="optlabel">?timeout</span>:float <span class="arrow">&#45;&gt;</span></span>
<span><span class="optlabel">?buf_size</span>:int <span class="arrow">&#45;&gt;</span></span>
<span><span class="optlabel">?get_time_s</span>:<span>(<span>unit <span class="arrow">&#45;&gt;</span></span> float)</span> <span class="arrow">&#45;&gt;</span></span>
<span><span class="optlabel">?new_thread</span>:<span>(<span><span>(<span>unit <span class="arrow">&#45;&gt;</span></span> unit)</span> <span class="arrow">&#45;&gt;</span></span> unit)</span> <span class="arrow">&#45;&gt;</span></span>
<span><span class="optlabel">?addr</span>:string <span class="arrow">&#45;&gt;</span></span>
<span><span class="optlabel">?port</span>:int <span class="arrow">&#45;&gt;</span></span>
<span><span class="optlabel">?sock</span>:<a href="../../ocaml/Unix/index.html#type-file_descr">Unix.file_descr</a> <span class="arrow">&#45;&gt;</span></span>
<span><span class="optlabel">?middlewares</span>:<span><span>(<span>[ `Encoding <span><span>| `Stage</span> of int</span> ]</span> * <a href="../Tiny_httpd_server/Middleware/index.html#type-t">Middleware.t</a>)</span> list</span> <span class="arrow">&#45;&gt;</span></span>
<span>unit <span class="arrow">&#45;&gt;</span></span>
<a href="#type-t">t</a></span></code></div><div class="spec-doc"><p>Create a new webserver using UNIX abstractions.</p><p>The server will not do anything until <a href="#val-run"><code>run</code></a> is called on it. Before starting the server, one can use <code>add_path_handler</code> and <a href="#val-set_top_handler"><code>set_top_handler</code></a> to specify how to handle incoming requests.</p><ul class="at-tags"><li class="parameter"><span class="at-tag">parameter</span> <span class="value">masksigpipe</span> <p>if true, block the signal <code>Sys.sigpipe</code> which otherwise tends to kill client threads when they try to write on broken sockets. Default: <code>true</code>.</p></li></ul><ul class="at-tags"><li class="parameter"><span class="at-tag">parameter</span> <span class="value">buf_size</span> <p>size for buffers (since 0.11)</p></li></ul><ul class="at-tags"><li class="parameter"><span class="at-tag">parameter</span> <span class="value">new_thread</span> <p>a function used to spawn a new thread to handle a new client connection. By default it is <code>Thread.create</code> but one could use a thread pool instead. See for example <a href="https://github.com/c-cube/tiny-httpd-moonpool-bench/blob/0dcbbffb4fe34ea4ad79d46343ad0cebb69ca69f/examples/t1.ml#L31">this use of moonpool</a>.</p></li></ul><ul class="at-tags"><li class="parameter"><span class="at-tag">parameter</span> <span class="value">middlewares</span> <p>see <a href="#val-add_middleware"><code>add_middleware</code></a> for more details.</p></li></ul><ul class="at-tags"><li class="parameter"><span class="at-tag">parameter</span> <span class="value">max_connections</span> <p>maximum number of simultaneous connections.</p></li></ul><ul class="at-tags"><li class="parameter"><span class="at-tag">parameter</span> <span class="value">timeout</span> <p>connection is closed if the socket does not do read or write for the amount of second. Default: 0.0 which means no timeout. timeout is not recommended when using proxy.</p></li></ul><ul class="at-tags"><li class="parameter"><span class="at-tag">parameter</span> <span class="value">addr</span> <p>address (IPv4 or IPv6) to listen on. Default <code>&quot;127.0.0.1&quot;</code>.</p></li></ul><ul class="at-tags"><li class="parameter"><span class="at-tag">parameter</span> <span class="value">port</span> <p>to listen on. Default <code>8080</code>.</p></li></ul><ul class="at-tags"><li class="parameter"><span class="at-tag">parameter</span> <span class="value">sock</span> <p>an existing socket given to the server to listen on, e.g. by systemd on Linux (or launchd on macOS). If passed in, this socket will be used instead of the <code>addr</code> and <code>port</code>. If not passed in, those will be used. This parameter exists since 0.10.</p></li></ul><ul class="at-tags"><li class="parameter"><span class="at-tag">parameter</span> <span class="value">get_time_s</span> <p>obtain the current timestamp in seconds. This parameter exists since 0.11.</p></li></ul></div></div><div class="odoc-spec"><div class="spec module-type anchored" id="module-type-IO_BACKEND"><a href="#module-type-IO_BACKEND" class="anchor"></a><code><span><span class="keyword">module</span> <span class="keyword">type</span> IO_BACKEND</span><span> = <a href="../Tiny_httpd_server/module-type-IO_BACKEND/index.html">Tiny_httpd_server.IO_BACKEND</a></span></code></div><div class="spec-doc"><p>A backend that provides IO operations, network operations, etc.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-create_from"><a href="#val-create_from" class="anchor"></a><code><span><span class="keyword">val</span> create_from :
<span><span class="optlabel">?buf_size</span>:int <span class="arrow">&#45;&gt;</span></span>
<span><span class="optlabel">?middlewares</span>:<span><span>(<span>[ `Encoding <span><span>| `Stage</span> of int</span> ]</span> * <a href="../Tiny_httpd_server/Middleware/index.html#type-t">Middleware.t</a>)</span> list</span> <span class="arrow">&#45;&gt;</span></span>
<span><span class="label">backend</span>:<span>(<span class="keyword">module</span> <a href="module-type-IO_BACKEND/index.html">IO_BACKEND</a>)</span> <span class="arrow">&#45;&gt;</span></span>
<span>unit <span class="arrow">&#45;&gt;</span></span>
<a href="#type-t">t</a></span></code></div><div class="spec-doc"><p>Create a new webserver using provided backend.</p><p>The server will not do anything until <a href="#val-run"><code>run</code></a> is called on it. Before starting the server, one can use <code>add_path_handler</code> and <a href="#val-set_top_handler"><code>set_top_handler</code></a> to specify how to handle incoming requests.</p><ul class="at-tags"><li class="parameter"><span class="at-tag">parameter</span> <span class="value">buf_size</span> <p>size for buffers (since 0.11)</p></li></ul><ul class="at-tags"><li class="parameter"><span class="at-tag">parameter</span> <span class="value">middlewares</span> <p>see <a href="#val-add_middleware"><code>add_middleware</code></a> for more details.</p></li></ul><ul class="at-tags"><li class="since"><span class="at-tag">since</span> 0.14</li></ul></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-addr"><a href="#val-addr" class="anchor"></a><code><span><span class="keyword">val</span> addr : <span><a href="#type-t">t</a> <span class="arrow">&#45;&gt;</span></span> string</span></code></div><div class="spec-doc"><p>Address on which the server listens.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-is_ipv6"><a href="#val-is_ipv6" class="anchor"></a><code><span><span class="keyword">val</span> is_ipv6 : <span><a href="#type-t">t</a> <span class="arrow">&#45;&gt;</span></span> bool</span></code></div><div class="spec-doc"><p><code>is_ipv6 server</code> returns <code>true</code> iff the address of the server is an IPv6 address.</p><ul class="at-tags"><li class="since"><span class="at-tag">since</span> 0.3</li></ul></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-port"><a href="#val-port" class="anchor"></a><code><span><span class="keyword">val</span> port : <span><a href="#type-t">t</a> <span class="arrow">&#45;&gt;</span></span> int</span></code></div><div class="spec-doc"><p>Port on which the server listens. Note that this might be different than the port initially given if the port was <code>0</code> (meaning that the OS picks a port for us).</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-active_connections"><a href="#val-active_connections" class="anchor"></a><code><span><span class="keyword">val</span> active_connections : <span><a href="#type-t">t</a> <span class="arrow">&#45;&gt;</span></span> int</span></code></div><div class="spec-doc"><p>Number of currently active connections.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-add_decode_request_cb"><a href="#val-add_decode_request_cb" class="anchor"></a><code><span><span class="keyword">val</span> add_decode_request_cb :
<span><a href="#type-t">t</a> <span class="arrow">&#45;&gt;</span></span>
<span><span>(<span><span>unit <a href="../Tiny_httpd_server/Request/index.html#type-t">Request.t</a></span> <span class="arrow">&#45;&gt;</span></span> <span><span>(<span>unit <a href="../Tiny_httpd_server/Request/index.html#type-t">Request.t</a></span> * <span>(<span><a href="#type-byte_stream">byte_stream</a> <span class="arrow">&#45;&gt;</span></span> <a href="#type-byte_stream">byte_stream</a>)</span>)</span> option</span>)</span> <span class="arrow">&#45;&gt;</span></span>
unit</span></code></div><div class="spec-doc"><p>Add a callback for every request. The callback can provide a stream transformer and a new request (with modified headers, typically). A possible use is to handle decompression by looking for a <code>Transfer-Encoding</code> header and returning a stream transformer that decompresses on the fly.</p><ul class="at-tags"><li class="deprecated"><span class="at-tag">deprecated</span> <p>use <a href="#val-add_middleware"><code>add_middleware</code></a> instead</p></li></ul></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-add_encode_response_cb"><a href="#val-add_encode_response_cb" class="anchor"></a><code><span><span class="keyword">val</span> add_encode_response_cb :
<span><a href="#type-t">t</a> <span class="arrow">&#45;&gt;</span></span>
<span><span>(<span><span>unit <a href="../Tiny_httpd_server/Request/index.html#type-t">Request.t</a></span> <span class="arrow">&#45;&gt;</span></span> <span><a href="../Tiny_httpd_server/Response/index.html#type-t">Response.t</a> <span class="arrow">&#45;&gt;</span></span> <span><a href="../Tiny_httpd_server/Response/index.html#type-t">Response.t</a> option</span>)</span> <span class="arrow">&#45;&gt;</span></span>
unit</span></code></div><div class="spec-doc"><p>Add a callback for every request/response pair. Similarly to <a href="#val-add_encode_response_cb"><code>add_encode_response_cb</code></a> the callback can return a new response, for example to compress it. The callback is given the query with only its headers, as well as the current response.</p><ul class="at-tags"><li class="deprecated"><span class="at-tag">deprecated</span> <p>use <a href="#val-add_middleware"><code>add_middleware</code></a> instead</p></li></ul></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-add_middleware"><a href="#val-add_middleware" class="anchor"></a><code><span><span class="keyword">val</span> add_middleware :
<span><span class="label">stage</span>:<span>[ `Encoding <span><span>| `Stage</span> of int</span> ]</span> <span class="arrow">&#45;&gt;</span></span>
<span><a href="#type-t">t</a> <span class="arrow">&#45;&gt;</span></span>
<span><a href="../Tiny_httpd_server/Middleware/index.html#type-t">Middleware.t</a> <span class="arrow">&#45;&gt;</span></span>
unit</span></code></div><div class="spec-doc"><p>Add a middleware to every request/response pair.</p><ul class="at-tags"><li class="parameter"><span class="at-tag">parameter</span> <span class="value">stage</span> <p>specify when middleware applies. Encoding comes first (outermost layer), then stages in increasing order.</p></li></ul><ul class="at-tags"><li class="raises"><span class="at-tag">raises</span> <code>Invalid_argument</code> <p>if stage is <code>`Stage n</code> where <code>n &lt; 1</code></p></li></ul><ul class="at-tags"><li class="since"><span class="at-tag">since</span> 0.11</li></ul></div></div><h5 id="request-handlers"><a href="#request-handlers" class="anchor"></a>Request handlers</h5><div class="odoc-spec"><div class="spec value anchored" id="val-set_top_handler"><a href="#val-set_top_handler" class="anchor"></a><code><span><span class="keyword">val</span> set_top_handler : <span><a href="#type-t">t</a> <span class="arrow">&#45;&gt;</span></span> <span><span>(<span><span><a href="#type-byte_stream">byte_stream</a> <a href="../Tiny_httpd_server/Request/index.html#type-t">Request.t</a></span> <span class="arrow">&#45;&gt;</span></span> <a href="../Tiny_httpd_server/Response/index.html#type-t">Response.t</a>)</span> <span class="arrow">&#45;&gt;</span></span> unit</span></code></div><div class="spec-doc"><p>Setup a handler called by default.</p><p>This handler is called with any request not accepted by any handler installed via <code>add_path_handler</code>. If no top handler is installed, unhandled paths will return a <code>404</code> not found</p><p>This used to take a <code>string Request.t</code> but it now takes a <code>byte_stream Request.t</code> since 0.14 . Use <a href="../Tiny_httpd_server/Request/index.html#val-read_body_full"><code>Request.read_body_full</code></a> to read the body into a string if needed.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-add_route_handler"><a href="#val-add_route_handler" class="anchor"></a><code><span><span class="keyword">val</span> add_route_handler :
<span><span class="optlabel">?accept</span>:<span>(<span><span>unit <a href="../Tiny_httpd_server/Request/index.html#type-t">Request.t</a></span> <span class="arrow">&#45;&gt;</span></span> <span><span>(unit, <a href="../Tiny_httpd_server/Response_code/index.html#type-t">Response_code.t</a> * string)</span> <a href="../../ocaml/Stdlib/index.html#type-result">result</a></span>)</span> <span class="arrow">&#45;&gt;</span></span>
<span><span class="optlabel">?middlewares</span>:<span><a href="../Tiny_httpd_server/Middleware/index.html#type-t">Middleware.t</a> list</span> <span class="arrow">&#45;&gt;</span></span>
<span><span class="optlabel">?meth</span>:<a href="../Tiny_httpd_server/Meth/index.html#type-t">Meth.t</a> <span class="arrow">&#45;&gt;</span></span>
<span><a href="#type-t">t</a> <span class="arrow">&#45;&gt;</span></span>
<span><span><span>(<span class="type-var">'a</span>, <span><span>string <a href="../Tiny_httpd_server/Request/index.html#type-t">Request.t</a></span> <span class="arrow">&#45;&gt;</span></span> <a href="../Tiny_httpd_server/Response/index.html#type-t">Response.t</a>)</span> <a href="../Tiny_httpd_server/Route/index.html#type-t">Route.t</a></span> <span class="arrow">&#45;&gt;</span></span>
<span><span class="type-var">'a</span> <span class="arrow">&#45;&gt;</span></span>
unit</span></code></div><div class="spec-doc"><p><code>add_route_handler server Route.(exact &quot;path&quot; @/ string @/ int @/ return) f</code> calls <code>f &quot;foo&quot; 42 request</code> when a <code>request</code> with path &quot;path/foo/42/&quot; is received.</p><p>Note that the handlers are called in the reverse order of their addition, so the last registered handler can override previously registered ones.</p><ul class="at-tags"><li class="parameter"><span class="at-tag">parameter</span> <span class="value">meth</span> <p>if provided, only accept requests with the given method. Typically one could react to <code>`GET</code> or <code>`PUT</code>.</p></li></ul><ul class="at-tags"><li class="parameter"><span class="at-tag">parameter</span> <span class="value">accept</span> <p>should return <code>Ok()</code> if the given request (before its body is read) should be accepted, <code>Error (code,message)</code> if it's to be rejected (e.g. because its content is too big, or for some permission error). See the <code>http_of_dir</code> program for an example of how to use <code>accept</code> to filter uploads that are too large before the upload even starts. The default always returns <code>Ok()</code>, i.e. it accepts all requests.</p></li></ul><ul class="at-tags"><li class="since"><span class="at-tag">since</span> 0.6</li></ul></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-add_route_handler_stream"><a href="#val-add_route_handler_stream" class="anchor"></a><code><span><span class="keyword">val</span> add_route_handler_stream :
<span><span class="optlabel">?accept</span>:<span>(<span><span>unit <a href="../Tiny_httpd_server/Request/index.html#type-t">Request.t</a></span> <span class="arrow">&#45;&gt;</span></span> <span><span>(unit, <a href="../Tiny_httpd_server/Response_code/index.html#type-t">Response_code.t</a> * string)</span> <a href="../../ocaml/Stdlib/index.html#type-result">result</a></span>)</span> <span class="arrow">&#45;&gt;</span></span>
<span><span class="optlabel">?middlewares</span>:<span><a href="../Tiny_httpd_server/Middleware/index.html#type-t">Middleware.t</a> list</span> <span class="arrow">&#45;&gt;</span></span>
<span><span class="optlabel">?meth</span>:<a href="../Tiny_httpd_server/Meth/index.html#type-t">Meth.t</a> <span class="arrow">&#45;&gt;</span></span>
<span><a href="#type-t">t</a> <span class="arrow">&#45;&gt;</span></span>
<span><span><span>(<span class="type-var">'a</span>, <span><span><a href="#type-byte_stream">byte_stream</a> <a href="../Tiny_httpd_server/Request/index.html#type-t">Request.t</a></span> <span class="arrow">&#45;&gt;</span></span> <a href="../Tiny_httpd_server/Response/index.html#type-t">Response.t</a>)</span> <a href="../Tiny_httpd_server/Route/index.html#type-t">Route.t</a></span> <span class="arrow">&#45;&gt;</span></span>
<span><span class="type-var">'a</span> <span class="arrow">&#45;&gt;</span></span>
unit</span></code></div><div class="spec-doc"><p>Similar to <a href="#val-add_route_handler"><code>add_route_handler</code></a>, but where the body of the request is a stream of bytes that has not been read yet. This is useful when one wants to stream the body directly into a parser, json decoder (such as <code>Jsonm</code>) or into a file.</p><ul class="at-tags"><li class="since"><span class="at-tag">since</span> 0.6</li></ul></div></div><h5 id="server-sent-events"><a href="#server-sent-events" class="anchor"></a>Server-sent events</h5><p><b>EXPERIMENTAL</b>: this API is not stable yet.</p><div class="odoc-spec"><div class="spec module-type anchored" id="module-type-SERVER_SENT_GENERATOR"><a href="#module-type-SERVER_SENT_GENERATOR" class="anchor"></a><code><span><span class="keyword">module</span> <span class="keyword">type</span> SERVER_SENT_GENERATOR</span><span> = <a href="../Tiny_httpd_server/module-type-SERVER_SENT_GENERATOR/index.html">Tiny_httpd_server.SERVER_SENT_GENERATOR</a></span></code></div><div class="spec-doc"><p>A server-side function to generate of Server-sent events.</p></div></div><div class="odoc-spec"><div class="spec type anchored" id="type-server_sent_generator"><a href="#type-server_sent_generator" class="anchor"></a><code><span><span class="keyword">type</span> server_sent_generator</span><span> = <span>(<span class="keyword">module</span> <a href="module-type-SERVER_SENT_GENERATOR/index.html">SERVER_SENT_GENERATOR</a>)</span></span></code></div><div class="spec-doc"><p>Server-sent event generator. This generates events that are forwarded to the client (e.g. the browser).</p><ul class="at-tags"><li class="since"><span class="at-tag">since</span> 0.9</li></ul></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-add_route_server_sent_handler"><a href="#val-add_route_server_sent_handler" class="anchor"></a><code><span><span class="keyword">val</span> add_route_server_sent_handler :
<span><span class="optlabel">?accept</span>:<span>(<span><span>unit <a href="../Tiny_httpd_server/Request/index.html#type-t">Request.t</a></span> <span class="arrow">&#45;&gt;</span></span> <span><span>(unit, <a href="../Tiny_httpd_server/Response_code/index.html#type-t">Response_code.t</a> * string)</span> <a href="../../ocaml/Stdlib/index.html#type-result">result</a></span>)</span> <span class="arrow">&#45;&gt;</span></span>
<span><a href="#type-t">t</a> <span class="arrow">&#45;&gt;</span></span>
<span><span><span>(<span class="type-var">'a</span>, <span><span>string <a href="../Tiny_httpd_server/Request/index.html#type-t">Request.t</a></span> <span class="arrow">&#45;&gt;</span></span> <span><a href="#type-server_sent_generator">server_sent_generator</a> <span class="arrow">&#45;&gt;</span></span> unit)</span> <a href="../Tiny_httpd_server/Route/index.html#type-t">Route.t</a></span> <span class="arrow">&#45;&gt;</span></span>
<span><span class="type-var">'a</span> <span class="arrow">&#45;&gt;</span></span>
unit</span></code></div><div class="spec-doc"><p>Add a handler on an endpoint, that serves server-sent events.</p><p>The callback is given a generator that can be used to send events as it pleases. The connection is always closed by the client, and the accepted method is always <code>GET</code>. This will set the header &quot;content-type&quot; to &quot;text/event-stream&quot; automatically and reply with a 200 immediately. See <a href="#type-server_sent_generator"><code>server_sent_generator</code></a> for more details.</p><p>This handler stays on the original thread (it is synchronous).</p><ul class="at-tags"><li class="since"><span class="at-tag">since</span> 0.9</li></ul></div></div><h5 id="upgrade-handlers"><a href="#upgrade-handlers" class="anchor"></a>Upgrade handlers</h5><p>These handlers upgrade the connection to another protocol.</p><ul class="at-tags"><li class="since"><span class="at-tag">since</span> NEXT_RELEASE</li></ul><div class="odoc-spec"><div class="spec module-type anchored" id="module-type-UPGRADE_HANDLER"><a href="#module-type-UPGRADE_HANDLER" class="anchor"></a><code><span><span class="keyword">module</span> <span class="keyword">type</span> UPGRADE_HANDLER</span><span> = <a href="../Tiny_httpd_server/module-type-UPGRADE_HANDLER/index.html">Tiny_httpd_server.UPGRADE_HANDLER</a></span></code></div><div class="spec-doc"><p>Handler that upgrades to another protocol.</p></div></div><div class="odoc-spec"><div class="spec type anchored" id="type-upgrade_handler"><a href="#type-upgrade_handler" class="anchor"></a><code><span><span class="keyword">type</span> upgrade_handler</span><span> = <span>(<span class="keyword">module</span> <a href="module-type-UPGRADE_HANDLER/index.html">UPGRADE_HANDLER</a>)</span></span></code></div><div class="spec-doc"><ul class="at-tags"><li class="since"><span class="at-tag">since</span> NEXT_RELEASE</li></ul></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-add_upgrade_handler"><a href="#val-add_upgrade_handler" class="anchor"></a><code><span><span class="keyword">val</span> add_upgrade_handler :
<span><span class="optlabel">?accept</span>:<span>(<span><span>unit <a href="../Tiny_httpd_server/Request/index.html#type-t">Request.t</a></span> <span class="arrow">&#45;&gt;</span></span> <span><span>(unit, <a href="../Tiny_httpd_server/Response_code/index.html#type-t">Response_code.t</a> * string)</span> <a href="../../ocaml/Stdlib/index.html#type-result">result</a></span>)</span> <span class="arrow">&#45;&gt;</span></span>
<span><a href="#type-t">t</a> <span class="arrow">&#45;&gt;</span></span>
<span><span><span>(<span class="type-var">'a</span>, <a href="#type-upgrade_handler">upgrade_handler</a>)</span> <a href="../Tiny_httpd_server/Route/index.html#type-t">Route.t</a></span> <span class="arrow">&#45;&gt;</span></span>
<span><span class="type-var">'a</span> <span class="arrow">&#45;&gt;</span></span>
unit</span></code></div></div><h5 id="run-the-server"><a href="#run-the-server" class="anchor"></a>Run the server</h5><div class="odoc-spec"><div class="spec value anchored" id="val-running"><a href="#val-running" class="anchor"></a><code><span><span class="keyword">val</span> running : <span><a href="#type-t">t</a> <span class="arrow">&#45;&gt;</span></span> bool</span></code></div><div class="spec-doc"><p>Is the server running?</p><ul class="at-tags"><li class="since"><span class="at-tag">since</span> 0.14</li></ul></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-stop"><a href="#val-stop" class="anchor"></a><code><span><span class="keyword">val</span> stop : <span><a href="#type-t">t</a> <span class="arrow">&#45;&gt;</span></span> unit</span></code></div><div class="spec-doc"><p>Ask the server to stop. This might not have an immediate effect as <a href="#val-run"><code>run</code></a> might currently be waiting on IO.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-run"><a href="#val-run" class="anchor"></a><code><span><span class="keyword">val</span> run : <span><span class="optlabel">?after_init</span>:<span>(<span>unit <span class="arrow">&#45;&gt;</span></span> unit)</span> <span class="arrow">&#45;&gt;</span></span> <span><a href="#type-t">t</a> <span class="arrow">&#45;&gt;</span></span> <span><span>(unit, exn)</span> <a href="../../ocaml/Stdlib/index.html#type-result">result</a></span></span></code></div><div class="spec-doc"><p>Run the main loop of the server, listening on a socket described at the server's creation time, using <code>new_thread</code> to start a thread for each new client.</p><p>This returns <code>Ok ()</code> if the server exits gracefully, or <code>Error e</code> if it exits with an error.</p><ul class="at-tags"><li class="parameter"><span class="at-tag">parameter</span> <span class="value">after_init</span> <p>is called after the server starts listening. since 0.13 .</p></li></ul></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-run_exn"><a href="#val-run_exn" class="anchor"></a><code><span><span class="keyword">val</span> run_exn : <span><span class="optlabel">?after_init</span>:<span>(<span>unit <span class="arrow">&#45;&gt;</span></span> unit)</span> <span class="arrow">&#45;&gt;</span></span> <span><a href="#type-t">t</a> <span class="arrow">&#45;&gt;</span></span> unit</span></code></div><div class="spec-doc"><p><code>run_exn s</code> is like <code>run s</code> but re-raises an exception if the server exits with an error.</p><ul class="at-tags"><li class="since"><span class="at-tag">since</span> 0.14</li></ul></div></div><h3 id="utils"><a href="#utils" class="anchor"></a>Utils</h3><div class="odoc-spec"><div class="spec module anchored" id="module-Util"><a href="#module-Util" class="anchor"></a><code><span><span class="keyword">module</span> Util</span><span> = <a href="../Tiny_httpd_util/index.html">Tiny_httpd_util</a></span></code></div></div><h3 id="resource-pool"><a href="#resource-pool" class="anchor"></a>Resource pool</h3><div class="odoc-spec"><div class="spec module anchored" id="module-Pool"><a href="#module-Pool" class="anchor"></a><code><span><span class="keyword">module</span> Pool</span><span> = <a href="../Tiny_httpd_pool/index.html">Tiny_httpd_pool</a></span></code></div></div><h3 id="static-directory-serving"><a href="#static-directory-serving" class="anchor"></a>Static directory serving</h3><div class="odoc-spec"><div class="spec module anchored" id="module-Dir"><a href="#module-Dir" class="anchor"></a><code><span><span class="keyword">module</span> Dir</span><span> = <a href="../Tiny_httpd_dir/index.html">Tiny_httpd_dir</a></span></code></div></div><div class="odoc-spec"><div class="spec module anchored" id="module-Html"><a href="#module-Html" class="anchor"></a><code><span><span class="keyword">module</span> Html</span><span> = <a href="../Tiny_httpd_html/index.html">Tiny_httpd_html</a></span></code></div><div class="spec-doc"><p>Alias to <a href="../Tiny_httpd_html/index.html"><code>Tiny_httpd_html</code></a></p></div></div></div></body></html>