Module Webs_unix

Webs Unix tooling.

Connection listeners

type listener = [
  1. | `Host of string * int

    Bind a socket on given hostname and port.

  2. | `Sockaddr of Unix.sockaddr

    Bind a socket on given address.

  3. | `Fd of Unix.file_descr

    Listen on that socket, the client is responsible for closing it.


The type for specifying the socket to listen for connections on.

val listener_localhost : listener

listener_localhost is `Host ("localhost", 8000).

val fd_of_listener : listener -> (Unix.file_descr * bool, string) Stdlib.result

fd_of_listener l is Ok (fd, close) a file descriptor fd for the specification l and close is true if the client is in charge of closing it. Unless l was `Fd, fd has close on exec set to true.

val listener_of_string : ?default_port:int -> string -> (listener, string) Stdlib.result

listener_of_string s parses a listen specification from s. The format is ADDR[:PORT] or PATH for a Unix domain socket. default_port is used if no port is specified, defaults to 8000.

The function here should not be ignored.

The function here should not be ignored

val pp_listener : Stdlib.Format.formatter -> listener -> unit

pp_listener formats an unspecified representation of listen values.


type Webs.Http.Resp.connection +=
  1. | Fd of Unix.file_descr

The type for Unix response connections. The file descriptor on which the response is written.

module Connector : sig ... end

Tools for writing connectors.

Sending files

See this section of the web service howto. To use the following you need a connector that supports Unix response connections.


type etagger = Webs.Http.fpath -> Unix.file_descr -> Unix.stats -> (Webs.Http.Etag.t, string) Stdlib.result

The type for functions for determining file etags. The function is given the filepath, a file descriptor open on it and its file stat record.

val default_etagger : etagger

default_etagger implements the nginx etag scheme namely the file stat's mtime and size written in lowercase hexadecimal as hex(mtime)-hex(size).

Directory responses

type dir_resp = etagger:etagger -> mime_types:Webs.Http.Mime_type.file_ext_map option -> Webs.Http.req -> Webs.Http.fpath -> (Webs.Http.resp, Webs.Http.resp) Stdlib.result

The type for functions for directory responses. Given an etagger, mime_types, the request and the file path to (existing) directory, the function should follow up with the response. If the response is a static file etagger and mime_types should be used to determine its etag and MIME type.

val dir_404 : dir_resp

dir_404 is a directory response that errors with Webs.Http.not_found_404.

val dir_index_file : string -> (dir_resp, string) Stdlib.result

dir_index_file file serves the file file in the directory via send_file. Errors if file contains a directory seperator or is "..".


val send_file : ?dir_resp:dir_resp -> ?etagger:etagger -> ?mime_types:Webs.Http.Mime_type.file_ext_map -> Webs.Http.req -> Webs.Http.fpath -> (Webs.Http.resp, Webs.Http.resp) Stdlib.result

send_file ~dir_resp ~etagger ~mime_types r file responds to r by sending file file, use Webs.Req.to_absolute_filepath to determine one from r safely.

More precisely it proceeds as follows:

  1. If file is a directory, continues with dir_resp (defaults to dir_404).
  2. If file is a file, an etag t is computed for file using etagger (defaults to default_etagger).

Equipped with the actual file and its etag the function proceeds to:

  1. Evaluate r's if-match header condition (if any) with tag t. If that is false, errors with a Webs.Http.precondition_failed_412 response.
  2. Evaluate r's if-none-match header condition with tag t. If that is false, responds with Webs.Http.not_modified_304
  3. If r is a HEAD request, respond with Webs.Http.ok_200 and an empty body at that point.
  4. If r has a range header, evaluate r's if-range header (if any) with tag t. If that is false, the range request is turned into a full response otherwise the first satisfiable range is served with Webs.Http.partial_content_206, if there is no satisifiable range, errors with Webs.Http.range_not_satisfiable_416.
  5. If r has no range header or the if-range condition failed respond with Webs.Http.ok_200 and a body with file's content.

The content type of the response is determined using Webs_kit.Mime_type.of_filepath with mime_types and file.

Responses include an Http.last_modified header derived from the file modification time. Apparently without this you do not hit the browser memory cache in blink based browsers.

In addition to the errors mentioned above, the function also errors with a:

Data is sent using a Webs.Resp.Direct response using the Webs_unix.Fd connection with the sendfile system call or a fallback if not available. For range requests a single range is responded with; there is no multipart/byteranges support for the time being.

Missing Unix bindings

val realpath : string -> string

realpath p is an absolute pathname for p obtained by resolving all extra / characters, relative path segments and symbolic links. Raises Unix.Unix_error.

Note. This can be removed once an OCaml version with this PR is required.

val sendfile : src:Unix.file_descr -> off:int -> len:int -> Unix.file_descr -> int

sendfile ~src ~off ~len writes len bytes starting at off in src to dst. Raises Unix.Unix_error, you'll also need to do the Unix.EINTR dance. Raises Sys_error if unsupported on the platform.

module Time : sig ... end

Measuring time.