Shuttle_http is a low level library for implementing HTTP/1.1 web services in OCaml using the Async library for lightweight concurrency. It allows defining services as simple OCaml functions, and supports streaming bodies to allow working with large bodies incrementally.
It supports error reporting using error handlers and provides a default implementation that responds with the error status code and an empty response body. Users can provide their own error handler implementation when setting up a server config. The library however only considers unhandled exceptions, and errors encountered while parsing the wire payload as use-cases that invoke the error handler. The expectation is that application specific errors will be dealt with by the user within their service definition.
Shuttle_http is not a framework and hence doesn't ship with any abstractions beyond service definitions needing to be a function that accept a request and return a deferred response.
A service definition in its most simple form might look like:
let my_service (request : Request.t) =
return (Response.create ~body:(Body.string "Hello World") `Ok)
We saw how to define services that respond with data that's entirely in memory. For some use-cases (Specially when working with really large bodies created from external sources like files), one might want to use a streaming body to serve large amounts of data without loading it all in memory:
let my_service (address : Socket.Address.Inet.t) (request : Request.t) =
let%map reader =
(* This an example to show a stream that works with an external resource. *)
Reader.open_file "<some file path>"
(* Create a pipe from the reader that we will use as a streaming response body. *)
let reader_pipe = Reader.pipe reader in
(* Create a response from the reader's pipe. If the server is closed before the full
response was served, the pipe will be closed which in-turn will close the reader and
the underlying file descriptor. *)
Response.create ~body:(Body.of_pipe `Chunked reader_pipe) `Ok
let main port =
Server.run_inet (Tcp.Where_to_listen.of_port port) my_service