Library
Module
Module type
Parameter
Class
Class type
HTTP server.
This module implements a very simple, basic HTTP/1.1 server using blocking IOs and threads.
It is possible to use a thread pool, see create
's argument new_thread
.
type buf = Tiny_httpd_buf.t
type byte_stream = Tiny_httpd_stream.t
module Meth : sig ... end
Headers are metadata associated with a request or response.
module Headers : sig ... end
Requests are sent by a client, e.g. a web browser or cURL. From the point of view of the server, they're inputs.
module Request : sig ... end
module Response_code : sig ... end
Responses are what a http server, such as Tiny_httpd
, send back to the client to answer a Request.t
module Response : sig ... end
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 Routes.
module Route : sig ... end
A middleware can be inserted in a handler to modify or observe its behavior.
module Middleware : sig ... end
A HTTP server. See create
for more details.
val create :
?masksigpipe:bool ->
?max_connections:int ->
?timeout:float ->
?buf_size:int ->
?get_time_s:(unit -> float) ->
?new_thread:((unit -> unit) -> unit) ->
?addr:string ->
?port:int ->
?sock:Unix.file_descr ->
?middlewares:([ `Encoding | `Stage of int ] * Middleware.t) list ->
unit ->
t
Create a new webserver.
The server will not do anything until run
is called on it. Before starting the server, one can use add_path_handler
and set_top_handler
to specify how to handle incoming requests.
val addr : t -> string
Address on which the server listens.
val is_ipv6 : t -> bool
is_ipv6 server
returns true
iff the address of the server is an IPv6 address.
val port : t -> int
Port on which the server listens. Note that this might be different than the port initially given if the port was 0
(meaning that the OS picks a port for us).
val active_connections : t -> int
Number of currently active connections.
val add_decode_request_cb :
t ->
(unit Request.t -> (unit Request.t * (byte_stream -> byte_stream)) option) ->
unit
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 Transfer-Encoding
header and returning a stream transformer that decompresses on the fly.
val add_encode_response_cb :
t ->
(unit Request.t -> Response.t -> Response.t option) ->
unit
Add a callback for every request/response pair. Similarly to add_encode_response_cb
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.
val add_middleware :
stage:[ `Encoding | `Stage of int ] ->
t ->
Middleware.t ->
unit
Add a middleware to every request/response pair.
val set_top_handler : t -> (string Request.t -> Response.t) -> unit
Setup a handler called by default.
This handler is called with any request not accepted by any handler installed via add_path_handler
. If no top handler is installed, unhandled paths will return a 404
not found.
val add_route_handler :
?accept:(unit Request.t -> (unit, Response_code.t * string) result) ->
?middlewares:Middleware.t list ->
?meth:Meth.t ->
t ->
('a, string Request.t -> Response.t) Route.t ->
'a ->
unit
add_route_handler server Route.(exact "path" @/ string @/ int @/ return) f
calls f "foo" 42 request
when a request
with path "path/foo/42/" is received.
Note that the handlers are called in the reverse order of their addition, so the last registered handler can override previously registered ones.
val add_route_handler_stream :
?accept:(unit Request.t -> (unit, Response_code.t * string) result) ->
?middlewares:Middleware.t list ->
?meth:Meth.t ->
t ->
('a, byte_stream Request.t -> Response.t) Route.t ->
'a ->
unit
Similar to add_route_handler
, 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 Jsonm
) or into a file.
EXPERIMENTAL: this API is not stable yet.
module type SERVER_SENT_GENERATOR = sig ... end
A server-side function to generate of Server-sent events.
type server_sent_generator = (module SERVER_SENT_GENERATOR)
Server-sent event generator. This generates events that are forwarded to the client (e.g. the browser).
val add_route_server_sent_handler :
?accept:(unit Request.t -> (unit, Response_code.t * string) result) ->
t ->
('a, string Request.t -> server_sent_generator -> unit) Route.t ->
'a ->
unit
Add a handler on an endpoint, that serves server-sent events.
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 GET
. This will set the header "content-type" to "text/event-stream" automatically and reply with a 200 immediately. See server_sent_generator
for more details.
This handler stays on the original thread (it is synchronous).
val stop : t -> unit
Ask the server to stop. This might not have an immediate effect as run
might currently be waiting on IO.
Run the main loop of the server, listening on a socket described at the server's creation time, using new_thread
to start a thread for each new client.
This returns Ok ()
if the server exits gracefully, or Error e
if it exits with an error.