FastCGI implementation in OCaml
at main 5.6 kB view raw
1(** FastCGI record handling for parsing and creating protocol messages. 2 3 This module provides the core functionality for handling FastCGI records, 4 which are the fundamental units of communication in the FastCGI protocol. 5 Records multiplex multiple requests over a single connection and provide 6 independent data streams within each request. *) 7 8(** {1 Record Structure} *) 9 10(** FastCGI protocol version *) 11type version = int 12 13(** Record types define the purpose and interpretation of record content *) 14type record = 15 | Begin_request (** Start a new FastCGI request *) 16 | Abort_request (** Abort an existing request *) 17 | End_request (** Terminate a request *) 18 | Params (** Name-value pairs (environment variables) *) 19 | Stdin (** Standard input data stream *) 20 | Stdout (** Standard output data stream *) 21 | Stderr (** Standard error data stream *) 22 | Data (** Additional data stream for Filter role *) 23 | Get_values (** Query application capabilities *) 24 | Get_values_result (** Response to capability query *) 25 | Unknown_type (** Unknown record type response *) 26 27(** [record_type_to_int rt] converts record type to its protocol integer value *) 28val record_to_int : record -> int 29 30(** [record_type_of_int i] converts protocol integer to record type. 31 Raises Invalid_argument for unknown values. *) 32val record_of_int : int -> record 33 34(** [pp_record ppf rt] pretty-prints a record type *) 35val pp_record : Format.formatter -> record -> unit 36 37(** Request identifier for multiplexing multiple requests over one connection. 38 Request ID 0 is reserved for management records. *) 39type request_id = int 40 41(** A complete FastCGI record containing header and content. 42 Records consist of an 8-byte fixed header followed by variable-length 43 content and optional padding for alignment. *) 44type t = { 45 version : version; (** Protocol version (always 1) *) 46 record_type : record; (** Type of this record *) 47 request_id : request_id; (** Request identifier *) 48 content : string; (** Record content data *) 49 offset : int; (** Offset within content string (default: 0) *) 50 length : int; (** Length to use from content (default: String.length content) *) 51} 52 53(** [pp ?max_content_len ppf record] pretty-prints a FastCGI record. 54 [max_content_len] limits the displayed content length (default: 100 bytes) *) 55val pp : ?max_content_len:int -> Format.formatter -> t -> unit 56 57(** {1 Record Operations} *) 58 59(** [read buf_read] reads a complete FastCGI record from the input buffer. 60 Returns the parsed record or raises an exception if the record is malformed 61 or if there's insufficient data. The padding is automatically handled and 62 discarded during parsing. *) 63val read : Eio.Buf_read.t -> t 64 65(** [write buf_write record] writes a FastCGI record to the output buffer. 66 The record header is automatically constructed from the record fields, 67 and appropriate padding is added to align the record on 8-byte boundaries 68 for optimal performance. Uses the record's offset and length fields to 69 determine which portion of the content to write. *) 70val write : Eio.Buf_write.t -> t -> unit 71 72(** [create ?version ~record ~request_id ~content ?offset ?length] creates a new record 73 with the specified parameters. Version defaults to 1 (the only supported version). 74 If offset and length are not provided, the entire content string is used. *) 75val create : ?version:version -> record:record -> 76 request_id:request_id -> content:string -> 77 ?offset:int -> ?length:int -> unit -> t 78 79(** {1 Key-Value Pairs} *) 80 81(** Key-value pairs are used to transmit environment variables and other 82 key-value data in FCGI_PARAMS and other record types. The FastCGI protocol 83 uses a specific encoding where lengths are variable-width (1 or 4 bytes). *) 84 85module KV : sig 86 (** Type for key-value pair collections *) 87 type t 88 89 (** [empty] creates an empty key-value pair collection *) 90 val empty : t 91 92 (** [add name value pairs] adds a key-value pair to the collection *) 93 val add : string -> string -> t -> t 94 95 (** [remove name pairs] removes all pairs with the given key *) 96 val remove : string -> t -> t 97 98 (** [find name pairs] returns the value associated with the given key. 99 Raises Not_found if the key is not present. *) 100 val find : string -> t -> string 101 102 (** [find_opt name pairs] returns Some value or None if not found *) 103 val find_opt : string -> t -> string option 104 105 (** [to_seq pairs] converts to a sequence of (key, value) tuples *) 106 val to_seq : t -> (string * string) Seq.t 107 108 (** [of_seq pairs] creates from a sequence of (key, value) tuples *) 109 val of_seq : (string * string) Seq.t -> t 110 111 (** [cardinal pairs] returns the number of key-value pairs *) 112 val cardinal : t -> int 113 114 (** [read buf_read] reads key-value pairs from a buffer. 115 Handles the FastCGI variable-length encoding where lengths ≤ 127 bytes 116 use 1 byte, longer lengths use 4 bytes with the high bit set. *) 117 val read : Eio.Buf_read.t -> t 118 119 (** [write buf_write pairs] writes key-value pairs to a buffer using 120 the FastCGI encoding format *) 121 val write : Eio.Buf_write.t -> t -> unit 122 123 (** [encode pairs] returns the encoded byte string representation *) 124 val encode : t -> string 125 126 (** [decode content] parses encoded key-value pairs from a string *) 127 val decode : string -> t 128 129 (** [pp ppf pairs] pretty-prints key-value pairs *) 130 val pp : Format.formatter -> t -> unit 131end