Http.Request
HTTP requests.
The service request and client request conventions may help understanding how connectors construct and use these values.
val make :
?headers:Headers.t ->
?path:Path.t ->
?query:string option ->
?scheme:Scheme.t ->
?service_path:Path.t ->
version:Version.t ->
Method.t ->
raw_path:string ->
Body.t ->
t
make method' ~raw_path body
is a request with given method'
, raw_path
and body
and:
headers
, the request headers. Defaults to Http.Headers.empty
. Note that in general it is better to let bodies define the content type and content length headers. See the client requests conventions.path
, see path
. Defaults to Path.none
.query
, see query
. Defaults to None
.scheme
is the scheme of the request, see scheme
. Defaults to `Https
.service_path
, see service_path
. Defaults to Path.root
.version
, the HTTP version, see version
.Usually you should rather use for_service_connector
or of_url
. This ensures that derived data like path
and query
are computed correctly.
val for_service_connector :
?scheme:Scheme.t ->
service_path:Path.t ->
version:Version.t ->
Method.t ->
raw_path:string ->
headers:Headers.t ->
Body.t ->
(t, Response.t) Stdlib.result
for_service_connector ~service_path ~version method'
~raw_path ~headers body
is a request that satisfies the service requests conventions.
In case the response cannot satisfy them an error response is returned according to the connector responses conventions.
val of_url :
?body:Body.t ->
?headers:Headers.t ->
?version:Version.t ->
Method.t ->
url:Webs_url.t ->
(t, string) Stdlib.result
of_url method' ~url body
is a scheme and method'
request on url
ensuring that the request satsifies the client request conventions.
headers
defaults to Headers.empty
and a suitable Headers.host
is added to it. body
defaults to Body.empty
, version
defaults to Version.v11
.
An error is returned if the scheme is neither http
or https
or if a decoding error occurs. Both path
and query
are derived with a service_path
of Path.root
.
val to_url : t -> (Webs_url.t, string) Stdlib.result
to_url request
is an URL for r
of the given scheme. This can be seen as the inverse of of_url
. This errors if no Headers.host
header can be found in the request header.
val to_url' : t -> Webs_url.t
to_url'
is like to_url
but raises Invalid_argument
if there is no Headers.host
header.
override_headers ~by request
is request
with headers Headers.override
(headers response) ~by
.
val pp : Stdlib.Format.formatter -> t -> unit
pp
formats responses for inspection. Guarantees not to consume the body
.
headers request
are the HTTP headers of request
. Should always at least includes at the Http.Headers.host
header.
method' request
is the HTTP method of request
.
path request
is the absolute path of the raw_path
of request
stripped by the service_path
of request
. This is the path you want your service to handle.
val query : t -> string option
val raw_path : t -> string
raw_path request
is the request target (HTTP/1.1) or :path
pseudo-header (HTTP/2, HTTP/3) of request
. Usually one rather wants to use the convenience path
and query
which are derived from this value as this makes the service insensitive to where it is attached, see service_path
.
scheme request
is the scheme of the request. Note that this is indicative. In particular services should not rely on this as this may depend on the way you are proxied or not be set by the connector. It it is mainly used by client connectors to be able to reconstruct the requested URL for example to follow redirections.
service_path r
is service path of r
.
version r
is the HTTP version of the request.
val echo : ?status:Status.t -> t -> Response.t
echo request
is a response with status status
(defaults to 404
) and a text/plain
body that has all the properties of request
, including the request body, which is consumed by the function with Body.to_string
.
Note. In general using echo
violates numerous HTTP musts.
Request deconstruction and response helpers. When they error these functions directly do with responses that have the right statuses and, unless otherwise noted, empty bodies.
val redirect_to_path :
?body:Body.t ->
?explain:string ->
?headers:Headers.t ->
?reason:string ->
t ->
Status.t ->
Path.t ->
Response.t
redirect_to_path request status path
redirects to path
in the service of request
. This is Response.redirect
status
loc
with loc
the result of encoding the path:
Path.concat (service_path request) path
val decode_header :
Headers.Name.t ->
(string -> ('a, string) Stdlib.result) ->
t ->
('a option, Response.t) Stdlib.result
decode_header h dec r
decodes header h
(if any) in r
. Errors with Http.Status.bad_request_400
in case of decoding errors and transfers the error message to Response.reason
.
val allow : 'a Method.constraint' list -> t -> ('a, Response.t) Stdlib.result
allow ms r
is:
Ok (Req.meth r)
if List.mem (Req.meth r, Req.meth r) ms
Error _
with a Http.Status.method_not_allowed_405
response otherwise.val find_cookie : name:string -> t -> (string option, string) Stdlib.result
find_cookie ~name r
is the value of cookie name
or None
if undefined in r
. Errors on header or cookie decoding errors.
FIXME. Why is this a string error ?
val to_query : t -> (Query.t, Response.t) Stdlib.result
to_query r
extracts a query from r
. This is
Ok q
with q
parsed from Req.query r
if r
's method is `GET
or `HEAD
.Ok q
with q
parsed from the request body on other methods and the content type is Media_type.application_x_www_form_urlencoded
. In this case the Webs.Http.Request.query
is ignored.Error _
with a:
Http.Status.unsupported_media_type_415
response if the content type is unsupportedHttp.Status.bad_request_400
reponse on decoding errors.Warning. Http.Query.t
values are untrusted, you need to properly validate their data.
val clean_path : t -> (unit, Response.t) Stdlib.result
clean_path r
is:
Ok ()
if r
's path is []
, [""]
or if it has no empty segment.Error _
with a Http.Status.moved_permanently_301
to r
's path without empty segments or the root if that results in the empty path.Note. 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 of this scheme is that no elaborate file extension logic on the final segment is needed to route file serving (I no longer understand this comment).
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.
val to_absolute_filepath :
?strip:Path.t ->
file_root:Path.fpath ->
t ->
(Path.fpath, Response.t) Stdlib.result
absolute_filepath ~strip ~file_root request
is:
Ok file
with file
an absolute file path strictly rooted in file_root
. file
is made by stripping strip
(defaults to [""]
) from r
's path
, converting the result to an absolute filepath and prefixing it with file_root
.Error r
with r
an empty Http.Status.not_found_404
response if stripping strip
results in None
and Http.Status.bad_request_400
if the absolute path conversion fails.val eval_if_none_match :
t ->
Etag.t ->
headers:Headers.t ->
(Headers.t, Response.t) Stdlib.result
eval_if_none_match request etag ~headers
is
Ok hs
with hs
the value headers
added with a Headers.etag
set to etag
. If request
has no Headers.if_none_match
header or if it has one and Etag.eval_if_none_match
returns true
on etag
.Error r
with r
an empty Http.Status.not_modified_304
response with headers headers
added with a Headers.etag
set to etag
. If r
has a Headers.if_none_match
header and that Etag.eval_if_none_match
returns false
.Error r
with r
an empty Http.Status.bad_request_400
response if the Headers.if_none_match
decoding errors.Design note. This slightly abuses the idea of the result
design idea which was rather to carry error responses in the Error _
case. But… it's convenient.