Tiny_httpd_core.Server
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
.
Exception raised to exit request handlers with a code+error message
A middleware can be inserted in a handler to modify or observe its behavior.
module Middleware : sig ... end
module Head_middleware : sig ... end
A middleware that only considers the request's head+headers.
module type IO_BACKEND = sig ... end
A backend that provides IO operations, network operations, etc.
val create_from :
?buf_size:int ->
?middlewares:([ `Encoding | `Stage of int ] * Middleware.t) list ->
backend:(module IO_BACKEND) ->
unit ->
t
Create a new webserver using provided backend.
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 * (IO.Input.t -> IO.Input.t)) 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 -> (IO.Input.t 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
This used to take a string Request.t
but it now takes a byte_stream Request.t
since 0.14 . Use Request.read_body_full
to read the body into a string if needed.
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, IO.Input.t 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) ->
?middlewares:Head_middleware.t list ->
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).
These handlers upgrade the connection to another protocol.
module type UPGRADE_HANDLER = sig ... end
Handler that upgrades to another protocol.
type upgrade_handler = (module UPGRADE_HANDLER)
val add_upgrade_handler :
?accept:(unit Request.t -> (unit, Response_code.t * string) result) ->
?middlewares:Head_middleware.t list ->
t ->
('a, upgrade_handler) Route.t ->
'a ->
unit
val running : t -> bool
Is the server running?
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.
val run_exn : ?after_init:(unit -> unit) -> t -> unit
run_exn s
is like run s
but re-raises an exception if the server exits with an error.