Documentation Index
Fetch the complete documentation index at: https://mintlify.com/avsm/httpz/llms.txt
Use this file to discover all available pages before exploring further.
The Res module provides HTTP response status codes and functions for writing responses to bigstring buffers for zero-copy I/O.
Status Type
status
type status =
(* 1xx Informational *)
| Continue
| Switching_protocols
(* 2xx Success *)
| Success
| Created
| Accepted
| No_content
| Partial_content
(* 3xx Redirection *)
| Moved_permanently
| Found
| See_other
| Not_modified
| Temporary_redirect
| Permanent_redirect
(* 4xx Client Error *)
| Bad_request
| Unauthorized
| Forbidden
| Not_found
| Method_not_allowed
| Not_acceptable
| Request_timeout
| Conflict
| Gone
| Length_required
| Precondition_failed
| Payload_too_large
| Uri_too_long
| Unsupported_media_type
| Range_not_satisfiable
| Expectation_failed
| Unprocessable_entity
| Upgrade_required
| Precondition_required
| Too_many_requests
(* 5xx Server Error *)
| Internal_server_error
| Not_implemented
| Bad_gateway
| Service_unavailable
| Gateway_timeout
| Http_version_not_supported
HTTP response status codes per RFC 7231 Section 6.
Status Constants
100 - Used for Expect: 100-continue
101 - Used for protocol Upgrade
2xx Success
200 OK - Standard success response
201 - Resource created successfully
202 - Request accepted for processing
204 - Success with no response body
206 - Used for Range requests
3xx Redirection
303 - Redirect to different URI
304 - Resource not modified (caching)
307 - Temporary redirect preserving method
308 - Permanent redirect preserving method
4xx Client Errors
401 - Authentication required
405 - HTTP method not allowed
406 - Cannot satisfy Accept headers
408 - Client took too long
409 - Request conflicts with current state
410 - Resource permanently removed
411 - Content-Length header required
412 - Conditional request failed
413 - Request body too large
414 - Request URI too long
415 - Unsupported Content-Type
416 - Invalid Range header
417 - Expect header cannot be met
422 - Semantic errors in request
426 - Client must upgrade protocol
428 - Conditional headers required
429 - Rate limit exceeded
5xx Server Errors
500 - Generic server error
501 - Functionality not supported
502 - Invalid response from upstream
503 - Server temporarily unavailable
Http_version_not_supported
505 - HTTP version not supported
Status Functions
status_code
val status_code : status -> int
Get numeric status code.
Example:
status_code Success (* Returns: 200 *)
status_code Not_found (* Returns: 404 *)
status_reason
val status_reason : status -> string
Get reason phrase.
Example:
status_reason Success (* Returns: "OK" *)
status_reason Not_found (* Returns: "Not Found" *)
status_to_string
val status_to_string : status -> string
Get “CODE Reason” string.
Example:
status_to_string Success (* Returns: "200 OK" *)
status_to_string Not_found (* Returns: "404 Not Found" *)
pp_status
val pp_status : Stdlib.Format.formatter -> status -> unit
Pretty-print status.
Response Writers
All write functions operate on bigstrings (Base_bigstring.t) for zero-copy I/O with Async’s Writer.write_bigstring. They use int16# offsets throughout and return the new offset after writing.
write_status_line
val write_status_line : Base_bigstring.t -> off:int16# -> status -> Version.t -> int16#
Write “HTTP/1.x CODE Reason\r\n” at offset.
HTTP version (Http_1_0 or Http_1_1)
Returns: New offset after writing
Example:
let off = Span.of_int 0 in
let off = Res.write_status_line buf ~off Success Version.Http_1_1 in
(* Writes: "HTTP/1.1 200 OK\r\n" *)
val write_header : Base_bigstring.t -> off:int16# -> string -> string -> int16#
Write “Name: Value\r\n” at offset using string name.
Returns: New offset after writing
Example:
let off = Res.write_header buf ~off "Content-Type" "application/json" in
(* Writes: "Content-Type: application/json\r\n" *)
val write_header_int : Base_bigstring.t -> off:int16# -> string -> int -> int16#
Write header with integer value using string name.
Returns: New offset after writing
Example:
let off = Res.write_header_int buf ~off "Content-Length" 1024 in
(* Writes: "Content-Length: 1024\r\n" *)
val write_header_name : Base_bigstring.t -> off:int16# -> Header_name.t -> string -> int16#
Write “Name: Value\r\n” using typed header name.
Returns: New offset after writing
Example:
let off = Res.write_header_name buf ~off Header_name.Content_type "text/html" in
(* Writes: "Content-Type: text/html\r\n" *)
val write_header_name_int : Base_bigstring.t -> off:int16# -> Header_name.t -> int -> int16#
Write header with integer value using typed header name.
Returns: New offset after writing
write_crlf
val write_crlf : Base_bigstring.t -> off:int16# -> int16#
Write “\r\n”.
Returns: New offset after writing
Example:
(* End of headers *)
let off = Res.write_crlf buf ~off in
write_content_length
val write_content_length : Base_bigstring.t -> off:int16# -> int -> int16#
Write “Content-Length: N\r\n”.
Returns: New offset after writing
Example:
let off = Res.write_content_length buf ~off 512 in
(* Writes: "Content-Length: 512\r\n" *)
write_connection
val write_connection : Base_bigstring.t -> off:int16# -> keep_alive:bool -> int16#
Write “Connection: keep-alive\r\n” or “Connection: close\r\n”.
Whether to use keep-alive
Returns: New offset after writing
Example:
let off = Res.write_connection buf ~off ~keep_alive:true in
(* Writes: "Connection: keep-alive\r\n" *)
Chunked Transfer Encoding
Functions for writing chunked transfer encoded responses per RFC 7230 Section 4.1. Use when response body length is unknown at the time headers are sent.
write_transfer_encoding_chunked
val write_transfer_encoding_chunked : Base_bigstring.t -> off:int16# -> int16#
Write “Transfer-Encoding: chunked\r\n”.
Returns: New offset after writing
val write_chunk_header : Base_bigstring.t -> off:int16# -> size:int -> int16#
Write chunk header "<hex-size>\r\n". Call before writing chunk data.
Size of the chunk data in bytes
Returns: New offset after writing
val write_chunk_footer : Base_bigstring.t -> off:int16# -> int16#
Write chunk footer “\r\n” after chunk data.
Returns: New offset after writing
write_final_chunk
val write_final_chunk : Base_bigstring.t -> off:int16# -> int16#
Write final chunk “0\r\n\r\n”. Call after all data chunks to signal end of body.
Returns: New offset after writing
Usage Examples
Simple Response
open Httpz
let send_simple_response buf content =
let off = Span.of_int 0 in
(* Status line *)
let off = Res.write_status_line buf ~off Success Version.Http_1_1 in
(* Headers *)
let off = Res.write_header buf ~off "Content-Type" "text/plain" in
let off = Res.write_content_length buf ~off (String.length content) in
let off = Res.write_connection buf ~off ~keep_alive:true in
(* End headers *)
let off = Res.write_crlf buf ~off in
(* Body *)
let off = Buf_write.string buf ~off content in
(* Send response *)
Writer.write_bigstring writer buf ~len:(Span.to_int off)
JSON Response
let send_json_response buf json_string =
let off = Span.of_int 0 in
let off = Res.write_status_line buf ~off Success Version.Http_1_1 in
let off = Res.write_header_name buf ~off Header_name.Content_type "application/json" in
let off = Res.write_content_length buf ~off (String.length json_string) in
let off = Res.write_crlf buf ~off in
let off = Buf_write.string buf ~off json_string in
send_to_client buf ~len:(Span.to_int off)
Error Response
let send_error buf status error_msg =
let off = Span.of_int 0 in
let off = Res.write_status_line buf ~off status Version.Http_1_1 in
let off = Res.write_header buf ~off "Content-Type" "text/plain" in
let off = Res.write_content_length buf ~off (String.length error_msg) in
let off = Res.write_crlf buf ~off in
let off = Buf_write.string buf ~off error_msg in
send_to_client buf ~len:(Span.to_int off)
Chunked Response
let send_chunked_response buf chunks =
let off = Span.of_int 0 in
(* Headers *)
let off = Res.write_status_line buf ~off Success Version.Http_1_1 in
let off = Res.write_header buf ~off "Content-Type" "text/plain" in
let off = Res.write_transfer_encoding_chunked buf ~off in
let off = Res.write_crlf buf ~off in
(* Send chunks *)
let off = List.fold chunks ~init:off ~f:(fun off chunk ->
let off = Res.write_chunk_header buf ~off ~size:(String.length chunk) in
let off = Buf_write.string buf ~off chunk in
Res.write_chunk_footer buf ~off
) in
(* Final chunk *)
let off = Res.write_final_chunk buf ~off in
send_to_client buf ~len:(Span.to_int off)
Redirect Response
let send_redirect buf location =
let off = Span.of_int 0 in
let off = Res.write_status_line buf ~off Found Version.Http_1_1 in
let off = Res.write_header_name buf ~off Header_name.Location location in
let off = Res.write_content_length buf ~off 0 in
let off = Res.write_crlf buf ~off in
send_to_client buf ~len:(Span.to_int off)