module Nethttpd_kernel:sig
..end
This module mainly defines the http_protocol
class which implements the
exchange of messages with a HTTP client. The request messages are represented
as sequence of req_token
values. The response is encapsulated in a separate
http_response
class. The contents of the response are represented as sequence
of resp_token
values.
typefatal_error =
[ `Broken_pipe
| `Broken_pipe_ignore
| `Message_too_long
| `Server_error
| `TLS_error of string * string
| `Timeout
| `Unix_error of Unix.error ]
These are the serious protocol violations after that the daemon stops any further processing.
Note that `Timeout
refers to a timeout in the middle of a request.
`Broken_pipe_ignore
is the "harmless" version of `Broken_pipe
(see config_suppress_broken_pipe
).
Long messages are fatal because it is suspected that they are denial
of service attacks. The kernel generates `Message_too_long
only for
long headers, not for long bodies.
Fatal server errors can happen when exceptions are not properly handled. As last resort the HTTP daemon closes the connection without notifying the client.
`TLS_error
means any error on the TLS level. The two strings identify
the problem as for Netsys_tls.Error
.
val string_of_fatal_error : fatal_error -> string
Convert error to a string, for logging
typebad_request_error =
[ `Bad_header
| `Bad_header_field of string
| `Bad_request_line
| `Bad_trailer
| `Format_error of string
| `Protocol_not_supported
| `Request_line_too_long
| `Unexpected_eof ]
A bad request is a violation where the current request cannot be decoded, and it is not possible to accept further requests over the current connection.
val string_of_bad_request_error : bad_request_error -> string
Convert error to a string, for logging
val status_of_bad_request_error : bad_request_error -> Nethttp.http_status
Returns the best response code for the error
typedata_chunk =
Stdlib.Bytes.t * int * int
A data_chunk
is a substring of a string. The substring is described by
the triple (s, pos, len)
where s
is the container, pos
is the
position where the substring begins, and len
its length.
typestatus_line =
int * string
= (code, phrase)
typetransfer_coding =
[ `Chunked | `Identity ]
typeresp_token =
[ `Resp_action of unit -> unit
| `Resp_body of data_chunk
| `Resp_end
| `Resp_header of Nethttp.http_header
| `Resp_info_line of status_line * Nethttp.http_header
| `Resp_status_line of status_line
| `Resp_trailer of Nethttp.http_trailer ]
The resp_token
represents a textual part of the response to send:
`Resp_info_line
is an informational status line (code=100..199). There can
be several informational lines, and they can be accompanied with their own
headers. Such lines are only sent to HTTP/1.1 clients.`Resp_status_line
is the final status line to send (code >= 200)`Resp_header
is the whole response header to send`Resp_body
is the next part of the response body to send.`Resp_trailer
is the whole response trailer to send (currently ignored)`Resp_action
is special because it does not directly represent a token
to send. The argument is a function which is called when the token is
the next token on the active event queue. The function is also called when
the event queue is dropped because of an error (the state of the
response object indicates this). The function must not raise exceptions
except Unix_error
, and it must not block.val resp_100_continue : resp_token
The predefined token for the "100 Continue" response
typeresp_state =
[ `Active | `Dropped | `Error | `Inhibited | `Processed | `Queued ]
The response state:
`Inhibited
= it is not yet allowed to start the response`Queued
= the response waits on the queue for activation`Active
= the response is currently being transmitted`Processed
= the response has been completely sent`Error
= an error occurred during the transmission of this response`Dropped
= an earlier response forced to close the connection, and
this response is dequeuedtypefront_token =
[ `Resp_end | `Resp_wire_data of data_chunk ]
Tokens generated by http_response
:
`Resp_wire_data
are data tokens.`Resp_end
indicates the end of the response.exception Send_queue_empty
typeannouncement =
[ `As of string | `Ignore | `Ocamlnet | `Ocamlnet_and of string ]
See config
class type http_response =object
..end
Encapsultation of the HTTP response for a single request
class http_response_impl :?close:bool -> ?suppress_body:bool -> int64 -> Nethttp.protocol -> announcement ->
http_response
Exported for debugging and testing only
val send_static_response : http_response ->
Nethttp.http_status -> Nethttp.http_header option -> Stdlib.Bytes.t -> unit
Sends the string argument as response body, together with the given status and the header (optional). Response header fields are set as follows:
Content-Length
is set to the length of the string.Content-Type
is set to "text/html" unless given by the header.
If the header object is passed in, these modifications are done
directly in this object as side effect.val send_file_response : http_response ->
Nethttp.http_status ->
Nethttp.http_header option -> Unix.file_descr -> int64 -> unit
Sends the contents of a file as response body, together with the given status and the header (optional). The descriptor must be a file descriptor (that cannot block). The int64 number is the length of the body. Response header fields are set as follows:
Content-Length
is set to the length of the string.Content-Type
is set to "text/html" unless given by the header.Note that Content-Range
is not set automatically, even if the file is only
partially transferred.
If the header object is passed in, these modifications are done directly in this object as side effect.
The function does not send the file immediately, but rather sets the http_response
object up that the next chunk of the file is added when the send queue becomes
empty. This file will be closed when the transfer is done.
typerequest_line =
Nethttp.http_method * Nethttp.protocol
The method (including the URI), and the HTTP version
typereq_token =
[ `Bad_request_error of
bad_request_error * http_response
| `Eof
| `Fatal_error of fatal_error
| `Req_body of data_chunk
| `Req_end
| `Req_expect_100_continue
| `Req_header of
request_line * Nethttp.http_header *
http_response
| `Req_trailer of Nethttp.http_trailer
| `Timeout ]
A req_token
represents a textual part of the received request:
`Req_header
is the full received header. Together with the header,
the corresponding http_response
object is returned which must
be used to transmit the response.`Req_expect_100_continue
is generated when the client expects that the
server sends a "100 Continue" response (or a final status code) now.
One should add `Resp_info_line resp_100_continue
to the send queue
if the header is acceptable, or otherwise generate an error response. In any
case, the rest of the request must be read until `Req_end
.`Req_body
is a part of the request body. The transfer-coding, if any,
is already decoded.`Req_trailer
is the received trailer`Req_end
indicates the end of the request (the next request may begin
immediately).`Eof
indicates the end of the stream`Bad_request_error
indicates that the request violated the HTTP protocol
in a serious way and cannot be decoded. It is required to send a
"400 Bad Request" response. The following token will be `Eof
.`Fatal_error
indicates that the connection crashed.
The following token will be `Eof
.`Timeout
means that nothing has been received for a certain amount
of time, and the protocol is in a state that the next request can begin.
The following token will be `Eof
.Note that it is always allowed to send
tokens to the client. The protocol
implementation takes care that the response is transmitted at the right point
in time.
val string_of_req_token : req_token -> string
For debugging
exception Recv_queue_empty
class type http_protocol_config =object
..end
Configuration values for the HTTP kernel
val default_http_protocol_config : http_protocol_config
Default config:
config_max_reqline_length = 32768
config_max_header_length = 65536
config_max_trailer_length = 32768
config_limit_pipeline_length = 5
config_limit_pipeline_size = 65536
config_announce_server = `Ocamlnet
config_suppress_broken_pipe = false
config_tls = None
class modify_http_protocol_config :?config_max_reqline_length:int -> ?config_max_header_length:int -> ?config_max_trailer_length:int -> ?config_limit_pipeline_length:int -> ?config_limit_pipeline_size:int -> ?config_announce_server:announcement -> ?config_suppress_broken_pipe:bool -> ?config_tls:Netsys_crypto_types.tls_config option -> http_protocol_config ->
http_protocol_config
Modifies the passed config object as specified by the optional arguments
class type http_protocol_hooks =object
..end
Allows it to set hooks for Nethttpd_kernel.http_protocol
class http_protocol :#http_protocol_config -> Unix.file_descr ->
object
..end
The core event loop of the HTTP daemon
class lingering_close :?preclose:unit -> unit -> Unix.file_descr ->
object
..end
Closes a file descriptor using the "lingering close" algorithm.
module Debug:sig
..end