Skip to main content

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

1xx Informational

Continue
status
100 - Used for Expect: 100-continue
Switching_protocols
status
101 - Used for protocol Upgrade

2xx Success

Success
status
200 OK - Standard success response
Created
status
201 - Resource created successfully
Accepted
status
202 - Request accepted for processing
No_content
status
204 - Success with no response body
Partial_content
status
206 - Used for Range requests

3xx Redirection

Moved_permanently
status
301 - Permanent redirect
Found
status
302 - Temporary redirect
See_other
status
303 - Redirect to different URI
Not_modified
status
304 - Resource not modified (caching)
Temporary_redirect
status
307 - Temporary redirect preserving method
Permanent_redirect
status
308 - Permanent redirect preserving method

4xx Client Errors

Bad_request
status
400 - Malformed request
Unauthorized
status
401 - Authentication required
Forbidden
status
403 - Access denied
Not_found
status
404 - Resource not found
Method_not_allowed
status
405 - HTTP method not allowed
Not_acceptable
status
406 - Cannot satisfy Accept headers
Request_timeout
status
408 - Client took too long
Conflict
status
409 - Request conflicts with current state
Gone
status
410 - Resource permanently removed
Length_required
status
411 - Content-Length header required
Precondition_failed
status
412 - Conditional request failed
Payload_too_large
status
413 - Request body too large
Uri_too_long
status
414 - Request URI too long
Unsupported_media_type
status
415 - Unsupported Content-Type
Range_not_satisfiable
status
416 - Invalid Range header
Expectation_failed
status
417 - Expect header cannot be met
Unprocessable_entity
status
422 - Semantic errors in request
Upgrade_required
status
426 - Client must upgrade protocol
Precondition_required
status
428 - Conditional headers required
Too_many_requests
status
429 - Rate limit exceeded

5xx Server Errors

Internal_server_error
status
500 - Generic server error
Not_implemented
status
501 - Functionality not supported
Bad_gateway
status
502 - Invalid response from upstream
Service_unavailable
status
503 - Server temporarily unavailable
Gateway_timeout
status
504 - Upstream timeout
Http_version_not_supported
status
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.
buf
Base_bigstring.t
Buffer to write to
off
int16#
Offset to write at
status
status
HTTP status code
version
Version.t
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" *)

write_header

val write_header : Base_bigstring.t -> off:int16# -> string -> string -> int16#
Write “Name: Value\r\n” at offset using string name.
buf
Base_bigstring.t
Buffer to write to
off
int16#
Offset to write at
name
string
Header name
value
string
Header value
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" *)

write_header_int

val write_header_int : Base_bigstring.t -> off:int16# -> string -> int -> int16#
Write header with integer value using string name.
buf
Base_bigstring.t
Buffer to write to
off
int16#
Offset to write at
name
string
Header name
value
int
Integer header value
Returns: New offset after writing Example:
let off = Res.write_header_int buf ~off "Content-Length" 1024 in
(* Writes: "Content-Length: 1024\r\n" *)

write_header_name

val write_header_name : Base_bigstring.t -> off:int16# -> Header_name.t -> string -> int16#
Write “Name: Value\r\n” using typed header name.
buf
Base_bigstring.t
Buffer to write to
off
int16#
Offset to write at
name
Header_name.t
Typed header name
value
string
Header value
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" *)

write_header_name_int

val write_header_name_int : Base_bigstring.t -> off:int16# -> Header_name.t -> int -> int16#
Write header with integer value using typed header name.
buf
Base_bigstring.t
Buffer to write to
off
int16#
Offset to write at
name
Header_name.t
Typed header name
value
int
Integer header value
Returns: New offset after writing

write_crlf

val write_crlf : Base_bigstring.t -> off:int16# -> int16#
Write “\r\n”.
buf
Base_bigstring.t
Buffer to write to
off
int16#
Offset to write at
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”.
buf
Base_bigstring.t
Buffer to write to
off
int16#
Offset to write at
len
int
Content length value
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”.
buf
Base_bigstring.t
Buffer to write to
off
int16#
Offset to write at
keep_alive
bool
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”.
buf
Base_bigstring.t
Buffer to write to
off
int16#
Offset to write at
Returns: New offset after writing

write_chunk_header

val write_chunk_header : Base_bigstring.t -> off:int16# -> size:int -> int16#
Write chunk header "<hex-size>\r\n". Call before writing chunk data.
buf
Base_bigstring.t
Buffer to write to
off
int16#
Offset to write at
size
int
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.
buf
Base_bigstring.t
Buffer to write to
off
int16#
Offset to write at
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.
buf
Base_bigstring.t
Buffer to write to
off
int16#
Offset to write at
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)