Module Webs.Req

HTTP requests.

Request bodies

type body = unit -> (bytes * int * int) option

The type for request bodies.

Bodies are blocking functions pulled by services to yield byte chunks of data of the request body as Some (bytes, first, len) values. The bytes value must not be modified and is readable from first to first+len until the next call to the function. The function returns None at the end of stream.

val empty_body : body

empty_body is an empty body.

val body_to_string : body -> string

body_to_string b accumulates the body to a string.

HTTP Requests

type t

The type for HTTP requests.

val v : ?service_root:Http.path -> ?version:Http.version -> ?body_length:int option -> ?body:body -> ?headers:Http.headers -> Http.meth -> string -> t

v meth request_target is an HTTP request with method meth, request target request_target, headers (defaults to Http.H.empty), body (defaults to empty_body), body_length (defaults to None or Some 0 if body is empty_body) and version (defaults to (1,1)).

val service_root : t -> Http.path

service_root r is the root path on which the service is served. Consult the documentation of connectors to understand how this is derived (usually from the gateway via a x-service-root header).

val version : t -> Http.version

version r is r's HTTP version.

val meth : t -> Http.meth

meth r is r's HTTP method.

val request_target : t -> string

request_target is r's request target. This should be the raw request, still percent encoded. Note that you usually rather want to use the convenience path and query which are derived from this value.

val path : t -> Http.path

path r is the absolute path of request_target. This is as a list of path segments or the empty list if the request target has no path. See the Http.path representation for details.

val query : t -> string option

query r is the query (without the '?') of request_target. Note that query string may be the empty string which is different from None (no '?' in the request target). To decode the query (and handle those that are POSTed) see to_query.

val headers : t -> Http.headers

headers r is r's HTTP headers. Includes at least the header.

val body_length : t -> int option

body_length r is r's request body length (if known).

val body : t -> body

body r is r's body.

val with_headers : Http.headers -> t -> t

with_headers hs r is r with headers hs.

val with_body : body_length:int option -> body -> t -> t

with_body blen b r is r with body length blen and body b.

val with_path : Http.path -> t -> t

with_path p r is r with path p.

val with_service_root : Http.path -> t -> t

with_service_root p r is r with service root r.

val pp : Stdlib.Format.formatter -> t -> unit

pp ppf req prints and unspecified representation of req on ppf but guarantees not to consume the body.

Request responses

Service redirect

val service_redirect : ?explain:string -> int -> Http.path -> t -> Resp.t

service_redirect status p r redirects r to the service path p (this means r's service_root is prefixed to p) with status status. See also Resp.redirect.


val echo : ?status:Http.status -> t -> Resp.t

echo r returns r as a 404 text/plain document (and by doing so violates numerous HTTP's musts). This includes the request body, which is consumed by the service.

Request deconstruction

Request deconstruction helpers. These functions directly error with responses that have the right statuses and empty bodies.

Header decoding

val decode_header : -> (string -> ('a, string) Stdlib.result) -> t -> ('a optionResp.t) Stdlib.result

decode_header h dec r decodes header h (if any) in r. Errors with Http.s400_bad_request in case of decoding errors.

Method constraints

module Allow : sig ... end

Method constraints.

Service forwarding


val forward_service : strip:Http.path -> t -> (tResp.t) Stdlib.result

forward_service ~strip r is:

FIXME. Because of the new behaviour of Http.Path.strip_prefix on root. This may introduce empty path segments that did not exist originally in the request when one concatenates the service root and the path. Would that be an argument to let also represent the root path ?

Absolute file paths

val to_absolute_filepath : ?strip:Http.path -> root:Http.fpath -> t -> (Http.fpathResp.t) Stdlib.result

absolute_filepath ~strip ~root r determines an absolute file path strictly rooted in root by stripping strip (defaults to [""]) from r's path, converting the result to an absolute filepath and prefixing it with docroot.

Errors with Http.s404_not_found if stripping strip results in None and Http.s400_bad_request if the absolute path conversion fails.


Warning. Http.Query.t values are untrusted, you need to properly validate their data.

val to_query : t -> (Http.Query.tResp.t) Stdlib.result

to_query r extracts a query from r. This is

Service routing

val to_service : strip:Http.path -> t -> (tResp.t) Stdlib.result

to_service ~strip r strips strip from r's path and appends it to the service root. Errors with Http.s404_not_found if stripping strip results in None.

Path cleaning

There's more than one way to handle empty segments and trailing slashes in request paths. The scheme proposed here simply always redirects to paths in which all empty segments, and thus trailing slashes, are removed; except on the root path. The advantage is that no elaborate file extension logic on the final segment is needed to route file serving.

val clean_path : t -> (tResp.t) Stdlib.result

clean_path r is:

  • Ok r if r's path is [], [""] or if it has no empty segment.
  • Error _ with a Http.s301_moved_permanently to r's path without empty segments or the root if that results in the empty path.

Warning. This cleaning does not touch dot segments or percent-encoded directory separators that may be present in the path. You should still use that function or to_absolute_filepath for mapping paths to file paths.