this repo has no description
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

more

+2087
+1
.gitignore
··· 1 + _build
+25
dune-project
··· 1 + (lang dune 3.0) 2 + 3 + (name fastcgi) 4 + 5 + (generate_opam_files true) 6 + 7 + (source 8 + (github ocaml/ocaml-fastcgi)) 9 + 10 + (authors "OCaml FastCGI Library Authors") 11 + 12 + (maintainers "OCaml FastCGI Library Authors") 13 + 14 + (license ISC) 15 + 16 + (documentation https://ocaml.github.io/ocaml-fastcgi/) 17 + 18 + (package 19 + (name fastcgi) 20 + (depends 21 + ocaml 22 + dune 23 + eio) 24 + (synopsis "FastCGI protocol implementation for OCaml using Eio") 25 + (description "A type-safe implementation of the FastCGI protocol for OCaml using the Eio effects-based IO library. Supports all three FastCGI roles: Responder, Authorizer, and Filter."))
+32
fastcgi.opam
··· 1 + # This file is generated by dune, edit dune-project instead 2 + opam-version: "2.0" 3 + synopsis: "FastCGI protocol implementation for OCaml using Eio" 4 + description: 5 + "A type-safe implementation of the FastCGI protocol for OCaml using the Eio effects-based IO library. Supports all three FastCGI roles: Responder, Authorizer, and Filter." 6 + maintainer: ["OCaml FastCGI Library Authors"] 7 + authors: ["OCaml FastCGI Library Authors"] 8 + license: "ISC" 9 + homepage: "https://github.com/ocaml/ocaml-fastcgi" 10 + doc: "https://ocaml.github.io/ocaml-fastcgi/" 11 + bug-reports: "https://github.com/ocaml/ocaml-fastcgi/issues" 12 + depends: [ 13 + "ocaml" 14 + "dune" {>= "3.0"} 15 + "eio" 16 + "odoc" {with-doc} 17 + ] 18 + build: [ 19 + ["dune" "subst"] {dev} 20 + [ 21 + "dune" 22 + "build" 23 + "-p" 24 + name 25 + "-j" 26 + jobs 27 + "@install" 28 + "@runtest" {with-test} 29 + "@doc" {with-doc} 30 + ] 31 + ] 32 + dev-repo: "git+https://github.com/ocaml/ocaml-fastcgi.git"
+18
lib/dune
··· 1 + (library 2 + (public_name fastcgi) 3 + (name fastcgi) 4 + (libraries eio) 5 + (modules 6 + fastcgi_types 7 + fastcgi 8 + fastcgi_protocol 9 + fastcgi_responder 10 + fastcgi_authorizer 11 + fastcgi_filter) 12 + (modules_without_implementation 13 + fastcgi_types 14 + fastcgi 15 + fastcgi_protocol 16 + fastcgi_responder 17 + fastcgi_authorizer 18 + fastcgi_filter))
+373
lib/fastcgi.mli
··· 1 + (** FastCGI protocol implementation for OCaml using Eio. 2 + 3 + This library provides a type-safe, high-performance implementation of the 4 + FastCGI protocol using OCaml's Eio effects-based IO library. It supports 5 + all three FastCGI roles: Responder, Authorizer, and Filter. 6 + 7 + FastCGI is an open extension to CGI that provides high performance for all 8 + Internet applications without the penalties of Web server APIs. Unlike 9 + traditional CGI programs that are started for each request, FastCGI 10 + applications are long-lived processes that can handle multiple requests 11 + over persistent connections. 12 + 13 + The library follows Eio conventions for structured concurrency, 14 + capability-based security, and resource management. All network I/O is 15 + performed using Eio's effects system, enabling high-performance concurrent 16 + request processing. 17 + 18 + {2 Key Features} 19 + 20 + - {b Type Safety}: Leverages OCaml's type system to prevent protocol errors 21 + - {b High Performance}: Connection multiplexing and keep-alive for efficiency 22 + - {b Structured Concurrency}: Automatic resource cleanup using Eio switches 23 + - {b All FastCGI Roles}: Complete support for Responder, Authorizer, and Filter 24 + - {b Standards Compliant}: Full implementation of FastCGI Protocol 1.0 25 + 26 + {2 Usage Example} 27 + 28 + {[ 29 + let hello_handler request response = 30 + let http_req = Responder.request_of_fastcgi request in 31 + let http_resp = Responder.response_of_fastcgi response in 32 + 33 + http_resp.write_status 200; 34 + http_resp.write_header "Content-Type" "text/html"; 35 + http_resp.write_body "<h1>Hello, FastCGI!</h1>"; 36 + http_resp.finish (); 37 + 38 + { app_status = 0; protocol_status = Request_complete } 39 + 40 + let () = Eio_main.run @@ fun env -> 41 + let net = Eio.Stdenv.net env in 42 + Switch.run @@ fun sw -> 43 + Server.run_default ~sw ~net 44 + ~handler:(Handler.Responder hello_handler) 45 + ~listen_address:(`Tcp (Eio.Net.Sockaddr.stream, 9000)) 46 + ]} 47 + 48 + {2 References} 49 + 50 + - {{:https://github.com/ocaml-multicore/eio} Eio Documentation} *) 51 + 52 + (** {1 Core Types} *) 53 + 54 + (** Re-export core types from Fastcgi_types. 55 + 56 + This includes all the fundamental FastCGI protocol types such as 57 + [record_type], [role], [request], [response], and protocol constants. 58 + This includes all the fundamental FastCGI protocol types. *) 59 + include module type of Fastcgi_types 60 + 61 + (** {1 Application Interface} *) 62 + 63 + (** Application handler signatures. 64 + 65 + This module defines the core handler types that applications implement 66 + to process FastCGI requests. Each handler type corresponds to one of 67 + the three FastCGI roles: Responder, Authorizer, and Filter. *) 68 + module Handler : sig 69 + (** Responder handler: process HTTP request and generate response. 70 + 71 + This is the most common handler type, equivalent to traditional CGI. 72 + A Responder FastCGI application has the same purpose as a CGI/1.1 program: 73 + it receives all the information associated with an HTTP request and generates 74 + an HTTP response. 75 + 76 + @param request Complete FastCGI request with parameters and input streams 77 + @param response Output streams for writing response data 78 + @return Response result with application and protocol status *) 79 + type 'a responder = 'a request -> 'a response -> response_result 80 + 81 + (** Authorizer handler: make authorization decision. 82 + 83 + An Authorizer FastCGI application receives all the information associated 84 + with an HTTP request and generates an authorized/unauthorized decision. 85 + In case of an authorized decision, the Authorizer can also associate 86 + name-value pairs with the HTTP request. 87 + 88 + @param request FastCGI request with authentication context 89 + @param response Output streams for authorization response 90 + @return Response result indicating authorization decision *) 91 + type 'a authorizer = 'a request -> 'a response -> response_result 92 + 93 + (** Filter handler: process data stream with filtering. 94 + 95 + A Filter FastCGI application receives all the information associated 96 + with an HTTP request, plus an extra stream of data from a file stored 97 + on the Web server, and generates a 'filtered' version of the data stream 98 + as an HTTP response. 99 + 100 + @param request FastCGI request including both HTTP context and file data 101 + @param response Output streams for filtered response 102 + @return Response result with filtered content status *) 103 + type 'a filter = 'a request -> 'a response -> response_result 104 + 105 + (** Generic handler that can handle any role. 106 + 107 + This variant type allows applications to support multiple roles or 108 + to be configured at runtime for different roles. The web server 109 + specifies the desired role in each Begin_request record. *) 110 + type 'a handler = 111 + | Responder of 'a responder (** Handle HTTP requests and responses *) 112 + | Authorizer of 'a authorizer (** Handle authorization decisions *) 113 + | Filter of 'a filter (** Handle data filtering *) 114 + end 115 + 116 + (** Application configuration. 117 + 118 + This type encapsulates all the settings needed to configure a FastCGI 119 + application's behavior. It includes both resource limits and the 120 + application logic (handler function). 121 + 122 + The configuration values affect how the application responds to 123 + FCGI_GET_VALUES management queries from the web server. *) 124 + type 'a app_config = { 125 + max_connections : int; (** Maximum concurrent transport connections 126 + this application will accept. Corresponds to 127 + FCGI_MAX_CONNS management variable. *) 128 + max_requests : int; (** Maximum concurrent requests this application 129 + will accept across all connections. Corresponds 130 + to FCGI_MAX_REQS management variable. *) 131 + multiplex_connections : bool; (** Whether this application can multiplex 132 + connections (handle concurrent requests over 133 + each connection). Corresponds to FCGI_MPXS_CONNS 134 + management variable. *) 135 + handler : 'a Handler.handler; (** Application request handler that implements 136 + the core application logic. *) 137 + } 138 + 139 + (** {1 Connection Management} *) 140 + 141 + (** Connection manager for handling FastCGI protocol. 142 + 143 + This module provides low-level connection management for FastCGI applications. 144 + It handles the binary protocol details, record parsing/serialization, and 145 + request multiplexing over individual transport connections. 146 + 147 + After a FastCGI process accepts a connection on its listening socket, the 148 + process executes a simple protocol to receive and send data. The protocol 149 + serves two purposes: First, it multiplexes a single transport connection 150 + between several independent FastCGI requests. Second, within each request 151 + the protocol provides several independent data streams in each direction. *) 152 + module Connection : sig 153 + (** Opaque connection type. 154 + 155 + Represents a single transport connection from a web server. The connection 156 + handles protocol parsing, request demultiplexing, and stream management. 157 + Each connection can handle multiple concurrent requests if the application 158 + supports multiplexing. *) 159 + type 'a t 160 + 161 + (** Connection statistics. 162 + 163 + Provides runtime metrics about connection usage for monitoring and 164 + debugging purposes. These statistics can help tune application 165 + performance and detect potential issues. *) 166 + type stats = { 167 + active_requests : int; (** Number of requests currently being processed 168 + on this connection. *) 169 + total_requests : int; (** Total number of requests processed since 170 + connection establishment. *) 171 + bytes_sent : int; (** Total bytes sent to the web server (responses). *) 172 + bytes_received : int; (** Total bytes received from the web server (requests). *) 173 + } 174 + 175 + (** Create a connection from a network flow. 176 + 177 + Initializes a new FastCGI connection over an established transport. 178 + The connection will parse incoming records and manage request state 179 + according to the FastCGI protocol. 180 + 181 + The connection handles a simple protocol to receive and send data, 182 + including record headers, content data, and proper multiplexing. 183 + 184 + @param sw Switch for managing connection lifetime and automatic cleanup 185 + @param flow Two-way network flow for bidirectional communication 186 + @return New connection ready to process FastCGI requests 187 + @raise Invalid_argument if the flow is already closed *) 188 + val create : sw:Eio.Switch.t -> 'a Eio.Flow.two_way -> 'a t 189 + 190 + (** Accept and process a single request on the connection. 191 + 192 + Waits for the next FastCGI request to arrive on this connection, 193 + then processes it using the provided handler. This function handles 194 + all protocol details including record parsing, stream management, 195 + and response generation. 196 + 197 + The function is concurrent-safe and can be called multiple times 198 + if the application supports request multiplexing. 199 + 200 + @param conn Connection to process request on 201 + @param handler Application handler for the request 202 + @return Promise that resolves to the response result when processing completes 203 + @raise Fastcgi.Error.Fastcgi_error on protocol violations *) 204 + val process_request : 'a t -> 'a Handler.handler -> response_result Eio.Promise.t 205 + 206 + (** Get connection statistics. 207 + 208 + Returns current runtime statistics for this connection. This information 209 + can be used for monitoring, load balancing decisions, and performance 210 + tuning. 211 + 212 + @param conn Connection to query 213 + @return Current statistics snapshot *) 214 + val stats : 'a t -> stats 215 + 216 + (** Close the connection gracefully. 217 + 218 + Closes the transport connection after completing any active requests. 219 + The Web server controls the lifetime of transport connections and can 220 + close a connection when no requests are active. 221 + 222 + @param conn Connection to close *) 223 + val close : 'a t -> unit 224 + end 225 + 226 + (** FastCGI server for accepting and managing connections. 227 + 228 + This module provides a high-level server that listens for incoming 229 + connections and manages them according to FastCGI protocol requirements. 230 + It handles connection acceptance, lifecycle management, and graceful 231 + shutdown. 232 + 233 + The server supports both Unix domain sockets and TCP sockets, as 234 + commonly used by web servers like nginx, Apache, and lighttpd. *) 235 + module Server : sig 236 + (** Server configuration. 237 + 238 + Complete configuration for a FastCGI server, including application 239 + settings, network binding, and resource limits. *) 240 + type 'a config = { 241 + app : 'a app_config; (** Application configuration including handlers 242 + and capability limits. *) 243 + listen_address : [ 244 + | `Unix of string (** Unix domain socket path. Common for local 245 + communication with web servers. *) 246 + | `Tcp of Eio.Net.Sockaddr.stream * int (** TCP socket address and port. 247 + Used for remote FastCGI servers. *) 248 + ]; 249 + backlog : int; (** Listen socket backlog size. Controls how 250 + many pending connections can be queued. *) 251 + max_connections : int; (** Maximum concurrent connections to accept. 252 + Should align with app.max_connections. *) 253 + } 254 + 255 + (** Run a FastCGI server. 256 + 257 + Starts a FastCGI server with the specified configuration. The server 258 + will listen for connections, accept them within the configured limits, 259 + and process requests using the application handler. 260 + 261 + The server implements the standard FastCGI application lifecycle: 262 + a FastCGI application calls accept() on the socket referred to by file 263 + descriptor FCGI_LISTENSOCK_FILENO to accept a new transport connection. 264 + 265 + This function blocks until the switch is cancelled or an error occurs. 266 + 267 + @param sw Switch for managing server lifetime and automatic cleanup 268 + @param net Network capability for creating listening sockets 269 + @param config Complete server configuration 270 + @raise Sys_error if unable to bind to the specified address *) 271 + val run : 272 + sw:Eio.Switch.t -> 273 + net:'a Eio.Net.t -> 274 + 'a config -> 275 + unit 276 + 277 + (** Run server with default configuration. 278 + 279 + Convenience function to start a FastCGI server with sensible defaults. 280 + Useful for simple applications that don't need custom configuration. 281 + 282 + Default settings: 283 + - max_connections: 10 284 + - max_requests: 50 285 + - multiplex_connections: true 286 + - backlog: 5 287 + 288 + @param sw Switch for managing server lifetime 289 + @param net Network capability for creating sockets 290 + @param handler Application handler function 291 + @param listen_address Address to listen on (Unix socket or TCP) 292 + @raise Sys_error if unable to bind to the specified address *) 293 + val run_default : 294 + sw:Eio.Switch.t -> 295 + net:'a Eio.Net.t -> 296 + handler:'a Handler.handler -> 297 + listen_address:[`Unix of string | `Tcp of Eio.Net.Sockaddr.stream * int] -> 298 + unit 299 + end 300 + 301 + (** {1 Error Handling} *) 302 + 303 + (** FastCGI specific errors. *) 304 + module Error : sig 305 + (** Error types. *) 306 + type t = 307 + | Protocol_error of string (** Protocol violation *) 308 + | Invalid_record of string (** Malformed record *) 309 + | Unsupported_version of int (** Unsupported protocol version *) 310 + | Unknown_record_type of int (** Unknown record type *) 311 + | Request_id_conflict of request_id (** Duplicate request ID *) 312 + | Connection_closed (** Connection unexpectedly closed *) 313 + | Application_error of string (** Application-specific error *) 314 + 315 + (** FastCGI exception. *) 316 + exception Fastcgi_error of t 317 + 318 + (** Convert error to string description. *) 319 + val to_string : t -> string 320 + 321 + (** Raise a FastCGI error. *) 322 + val raise : t -> 'a 323 + end 324 + 325 + (** {1 Resource Management} *) 326 + 327 + (** Resource management utilities. *) 328 + module Resource : sig 329 + (** Request context with automatic cleanup. *) 330 + type 'a request_context = { 331 + request : 'a request; 332 + response : 'a response; 333 + switch : Eio.Switch.t; (** Switch for request-scoped resources *) 334 + } 335 + 336 + (** Create a request context with automatic resource management. 337 + 338 + @param sw Parent switch 339 + @param request FastCGI request 340 + @param f Function to execute with request context 341 + @return Result of function execution *) 342 + val with_request_context : 343 + sw:Eio.Switch.t -> 344 + 'a request -> 345 + ('a request_context -> 'b) -> 346 + 'b 347 + 348 + (** Buffer management for efficient I/O. *) 349 + module Buffer : sig 350 + (** Buffer type. *) 351 + type t 352 + 353 + (** Create a buffer with specified size. *) 354 + val create : size:int -> t 355 + 356 + (** Read data into buffer from source. 357 + 358 + @param buffer Buffer to read into 359 + @param source Source to read from 360 + @return Number of bytes read *) 361 + val read_into : t -> 'a Eio.Flow.source -> int 362 + 363 + (** Write data from buffer to sink. 364 + 365 + @param buffer Buffer to write from 366 + @param sink Sink to write to 367 + @param length Number of bytes to write *) 368 + val write_from : t -> 'a Eio.Flow.sink -> int -> unit 369 + 370 + (** Clear buffer contents. *) 371 + val clear : t -> unit 372 + end 373 + end
+229
lib/fastcgi_authorizer.mli
··· 1 + (** Authorizer role implementation for FastCGI. 2 + 3 + The Authorizer role performs access control decisions for web requests. 4 + An Authorizer FastCGI application receives all the information associated 5 + with an HTTP request and generates an authorized/unauthorized decision. 6 + 7 + In case of an authorized decision, the Authorizer can associate name-value 8 + pairs with the HTTP request for use by subsequent processing stages. When 9 + giving an unauthorized decision, the Authorizer sends a complete response 10 + to the HTTP client with appropriate error information. 11 + 12 + This role is commonly used for: 13 + - Authentication and authorization checks 14 + - Access control based on IP addresses, user roles, or request attributes 15 + - Rate limiting and quota enforcement 16 + - Custom security policies 17 + 18 + The web server may proceed with additional access checks after a successful 19 + authorization, including requests to other Authorizers, depending on its 20 + configuration. *) 21 + 22 + (** {1 Authorization Types} *) 23 + 24 + (** Authorization result. 25 + 26 + Represents the outcome of an authorization decision. The Authorizer can 27 + either grant access (possibly with additional variables) or deny access 28 + with a complete error response. *) 29 + type auth_result = 30 + | Authorized of (string * string) list (** Request is authorized. The list contains 31 + variable bindings that will be added to 32 + the request environment for subsequent 33 + processing stages. *) 34 + | Unauthorized of { 35 + status : int; (** HTTP status code for the error response 36 + (typically 401, 403, or 429). *) 37 + headers : (string * string) list; (** HTTP headers for the error response. 38 + May include WWW-Authenticate, etc. *) 39 + body : string; (** Error response body content sent to the client. *) 40 + } (** Request is denied. The web server will send this error 41 + response directly to the client without further processing. *) 42 + 43 + (** Authorization request information. 44 + 45 + Contains the relevant information from an HTTP request needed to make 46 + authorization decisions. This is extracted from the CGI environment 47 + variables provided by the web server. *) 48 + type auth_request = { 49 + method_ : string; (** HTTP method (GET, POST, etc.). *) 50 + uri : string; (** Request URI being accessed. *) 51 + remote_addr : string option; (** Client IP address, if available. 52 + Useful for IP-based access control. *) 53 + remote_user : string option; (** Authenticated username, if any. 54 + Set by prior authentication stages. *) 55 + auth_type : string option; (** Authentication method used (Basic, Bearer, etc.). 56 + Indicates how the user was authenticated. *) 57 + headers : (string * string) list; (** HTTP headers from the request. 58 + May contain authorization headers, user agents, etc. *) 59 + } 60 + 61 + (** {1 Conversion Functions} *) 62 + 63 + (** Convert FastCGI request to authorization request. 64 + 65 + Extracts authorization-relevant information from FastCGI 66 + parameters and creates an auth request object. 67 + 68 + @param request FastCGI request 69 + @return Authorization request *) 70 + val request_of_fastcgi : 'a Fastcgi_types.request -> auth_request 71 + 72 + (** Convert authorization result to FastCGI response. 73 + 74 + Writes the authorization decision to the FastCGI response 75 + streams in the correct format. 76 + 77 + @param result Authorization decision 78 + @param response FastCGI response 79 + @return Response result *) 80 + val response_of_result : auth_result -> 'a Fastcgi_types.response -> Fastcgi_types.response_result 81 + 82 + (** {1 Handler Utilities} *) 83 + 84 + (** Authorizer handler type. *) 85 + type 'a authorizer_handler = 'a Fastcgi_types.request -> 'a Fastcgi_types.response -> Fastcgi_types.response_result 86 + 87 + (** Convenience handler wrapper for authorization handlers. 88 + 89 + Converts an authorization handler function into a FastCGI handler. 90 + This allows writing handlers that work with auth request/result 91 + types instead of raw FastCGI types. 92 + 93 + @param handler Authorization handler function 94 + @return FastCGI authorizer handler *) 95 + val auth_handler : 96 + (auth_request -> auth_result) -> 97 + 'a authorizer_handler 98 + 99 + (** {1 Common Authorization Patterns} *) 100 + 101 + (** Create a simple allow/deny authorizer. 102 + 103 + @param predicate Function that returns true for authorized requests 104 + @return Authorization result *) 105 + val simple_authorizer : (auth_request -> bool) -> (auth_request -> auth_result) 106 + 107 + (** IP-based authorization. 108 + 109 + @param allowed_ips List of allowed IP addresses/ranges 110 + @param request Authorization request 111 + @return Authorization result *) 112 + val ip_authorizer : string list -> auth_request -> auth_result 113 + 114 + (** User-based authorization. 115 + 116 + @param allowed_users List of allowed usernames 117 + @param request Authorization request 118 + @return Authorization result *) 119 + val user_authorizer : string list -> auth_request -> auth_result 120 + 121 + (** Role-based authorization. 122 + 123 + @param get_user_roles Function to get roles for a user 124 + @param required_roles Roles required for access 125 + @param request Authorization request 126 + @return Authorization result *) 127 + val role_authorizer : 128 + get_user_roles:(string -> string list) -> 129 + required_roles:string list -> 130 + auth_request -> 131 + auth_result 132 + 133 + (** Time-based authorization. 134 + 135 + @param allowed_hours List of allowed hours (0-23) 136 + @param request Authorization request 137 + @return Authorization result *) 138 + val time_authorizer : int list -> auth_request -> auth_result 139 + 140 + (** {1 Authentication Integration} *) 141 + 142 + (** Basic authentication handler. 143 + 144 + @param realm Authentication realm 145 + @param verify_credentials Function to verify username/password 146 + @param request Authorization request 147 + @return Authorization result *) 148 + val basic_auth : 149 + realm:string -> 150 + verify_credentials:(string -> string -> bool) -> 151 + auth_request -> 152 + auth_result 153 + 154 + (** Bearer token authentication. 155 + 156 + @param verify_token Function to verify and decode token 157 + @param request Authorization request 158 + @return Authorization result *) 159 + val bearer_auth : 160 + verify_token:(string -> (string * (string * string) list) option) -> 161 + auth_request -> 162 + auth_result 163 + 164 + (** API key authentication. 165 + 166 + @param header_name Header containing API key 167 + @param verify_key Function to verify API key 168 + @param request Authorization request 169 + @return Authorization result *) 170 + val api_key_auth : 171 + header_name:string -> 172 + verify_key:(string -> (string * (string * string) list) option) -> 173 + auth_request -> 174 + auth_result 175 + 176 + (** {1 Response Helpers} *) 177 + 178 + (** Create a standard 401 Unauthorized response. 179 + 180 + @param realm Authentication realm 181 + @param message Error message 182 + @return Unauthorized result *) 183 + val unauthorized_response : 184 + realm:string -> 185 + message:string -> 186 + auth_result 187 + 188 + (** Create a standard 403 Forbidden response. 189 + 190 + @param message Error message 191 + @return Unauthorized result *) 192 + val forbidden_response : 193 + message:string -> 194 + auth_result 195 + 196 + (** Create a custom error response. 197 + 198 + @param status HTTP status code 199 + @param headers Additional headers 200 + @param body Response body 201 + @return Unauthorized result *) 202 + val error_response : 203 + status:int -> 204 + headers:(string * string) list -> 205 + body:string -> 206 + auth_result 207 + 208 + (** {1 Variable Binding} *) 209 + 210 + (** Create authorized response with variables. 211 + 212 + Variables are passed to subsequent FastCGI applications 213 + as environment variables with "Variable-" prefix. 214 + 215 + @param variables Name-value pairs to bind 216 + @return Authorized result *) 217 + val authorized_with_variables : (string * string) list -> auth_result 218 + 219 + (** Add authentication information as variables. 220 + 221 + @param user Authenticated username 222 + @param auth_type Authentication method 223 + @param additional Additional variables 224 + @return Variable bindings *) 225 + val auth_variables : 226 + user:string -> 227 + auth_type:string -> 228 + additional:(string * string) list -> 229 + (string * string) list
+329
lib/fastcgi_filter.mli
··· 1 + (** Filter role implementation for FastCGI. 2 + 3 + The Filter role processes data streams with filtering capabilities. 4 + A Filter FastCGI application receives all the information associated with 5 + an HTTP request, plus an extra stream of data from a file stored on the 6 + web server, and generates a "filtered" version of the data stream as an 7 + HTTP response. 8 + 9 + This role is useful for: 10 + - Dynamic content transformation (e.g., server-side includes, templating) 11 + - Format conversion (e.g., Markdown to HTML, image resizing) 12 + - Content compression and optimization 13 + - Real-time content modification based on request context 14 + 15 + A Filter is similar in functionality to a Responder that takes a data file 16 + as a parameter. The key difference is that with a Filter, both the data file 17 + and the Filter itself can be access controlled using the web server's access 18 + control mechanisms, while a Responder that takes the name of a data file as 19 + a parameter must perform its own access control checks on the data file. 20 + 21 + The web server presents the Filter with environment variables first, then 22 + standard input (normally form POST data), and finally the data file input 23 + that needs to be processed. *) 24 + 25 + (** {1 Filter Types} *) 26 + 27 + (** Filter request with data stream. 28 + 29 + Represents a complete Filter request including both the HTTP request 30 + context and the data stream that needs to be processed. *) 31 + type 'a filter_request = { 32 + request : 'a Fastcgi_types.request; (** Base FastCGI request containing HTTP context, 33 + parameters, and form data. *) 34 + data_stream : 'a Eio.Flow.source; (** File data stream to be filtered. 35 + This is the content that needs processing. *) 36 + data_last_modified : float option; (** File modification time as seconds since epoch. 37 + Useful for caching and conditional requests. *) 38 + data_length : int option; (** Expected length of the data stream in bytes. 39 + May be None if length is unknown. *) 40 + } 41 + 42 + (** Filter metadata about the data being processed. *) 43 + type filter_metadata = { 44 + filename : string option; (** Original filename *) 45 + mime_type : string option; (** MIME type of data *) 46 + last_modified : float option; (** Last modification time *) 47 + size : int option; (** Data size in bytes *) 48 + etag : string option; (** Entity tag for caching *) 49 + } 50 + 51 + (** Filter context with additional processing information. *) 52 + type 'a filter_context = { 53 + filter_request : 'a filter_request; (** Request and data *) 54 + metadata : filter_metadata; (** File metadata *) 55 + cache_control : cache_policy; (** Caching policy *) 56 + } 57 + 58 + (** Cache policy for filtered content. *) 59 + and cache_policy = 60 + | No_cache (** No caching *) 61 + | Cache_for of int (** Cache for N seconds *) 62 + | Cache_until of float (** Cache until timestamp *) 63 + | Conditional_cache of (filter_metadata -> bool) (** Conditional caching *) 64 + 65 + (** {1 Conversion Functions} *) 66 + 67 + (** Convert FastCGI request to filter request. 68 + 69 + Extracts filter-specific information from FastCGI streams 70 + and creates a filter request object. 71 + 72 + @param request FastCGI request 73 + @return Filter request with data stream *) 74 + val request_of_fastcgi : 'a Fastcgi_types.request -> 'a filter_request 75 + 76 + (** Create filter context with metadata. 77 + 78 + @param filter_request Filter request 79 + @param metadata File metadata 80 + @param cache_control Caching policy 81 + @return Filter context *) 82 + val context_of_request : 83 + 'a filter_request -> 84 + metadata:filter_metadata -> 85 + cache_control:cache_policy -> 86 + 'a filter_context 87 + 88 + (** {1 Handler Utilities} *) 89 + 90 + (** Filter handler type. *) 91 + type 'a filter_handler = 'a Fastcgi_types.request -> 'a Fastcgi_types.response -> Fastcgi_types.response_result 92 + 93 + (** Convenience handler wrapper for filter handlers. 94 + 95 + Converts a filter handler function into a FastCGI handler. 96 + This allows writing handlers that work with filter request/response 97 + types instead of raw FastCGI types. 98 + 99 + @param handler Filter handler function 100 + @return FastCGI filter handler *) 101 + 102 + val filter_handler : 103 + ('a filter_request -> 'a Fastcgi_types.response -> unit) -> 104 + 'a filter_handler 105 + 106 + (** Context-aware filter handler. 107 + 108 + Similar to filter_handler but provides additional context 109 + including metadata and caching information. 110 + 111 + @param handler Context-aware filter handler 112 + @return FastCGI filter handler *) 113 + val context_filter_handler : 114 + ('a filter_context -> 'a Fastcgi_types.response -> unit) -> 115 + 'a filter_handler 116 + 117 + (** {1 Common Filter Operations} *) 118 + 119 + (** Text processing filters. *) 120 + module Text : sig 121 + (** Convert text encoding. 122 + 123 + @param from_encoding Source encoding 124 + @param to_encoding Target encoding 125 + @param input Text stream 126 + @param output Filtered stream *) 127 + val convert_encoding : 128 + from_encoding:string -> 129 + to_encoding:string -> 130 + input:'a Eio.Flow.source -> 131 + output:'a Eio.Flow.sink -> 132 + unit 133 + 134 + (** Find and replace text patterns. 135 + 136 + @param pattern Regular expression pattern 137 + @param replacement Replacement text 138 + @param input Text stream 139 + @param output Filtered stream *) 140 + val find_replace : 141 + pattern:string -> 142 + replacement:string -> 143 + input:'a Eio.Flow.source -> 144 + output:'a Eio.Flow.sink -> 145 + unit 146 + 147 + (** Template substitution. 148 + 149 + @param variables Variable substitutions 150 + @param input Template stream 151 + @param output Processed stream *) 152 + val template_substitute : 153 + variables:(string * string) list -> 154 + input:'a Eio.Flow.source -> 155 + output:'a Eio.Flow.sink -> 156 + unit 157 + 158 + (** Markdown to HTML conversion. 159 + 160 + @param options Markdown processing options 161 + @param input Markdown stream 162 + @param output HTML stream *) 163 + val markdown_to_html : 164 + options:string list -> 165 + input:'a Eio.Flow.source -> 166 + output:'a Eio.Flow.sink -> 167 + unit 168 + end 169 + 170 + (** Image processing filters. *) 171 + module Image : sig 172 + (** Image resize operation. 173 + 174 + @param width Target width 175 + @param height Target height 176 + @param input Image stream 177 + @param output Resized stream *) 178 + val resize : 179 + width:int -> 180 + height:int -> 181 + input:'a Eio.Flow.source -> 182 + output:'a Eio.Flow.sink -> 183 + unit 184 + 185 + (** Image format conversion. 186 + 187 + @param format Target format (jpeg, png, etc.) 188 + @param quality Quality setting (for lossy formats) 189 + @param input Image stream 190 + @param output Converted stream *) 191 + val convert_format : 192 + format:string -> 193 + quality:int option -> 194 + input:'a Eio.Flow.source -> 195 + output:'a Eio.Flow.sink -> 196 + unit 197 + 198 + (** Image compression. 199 + 200 + @param level Compression level 201 + @param input Image stream 202 + @param output Compressed stream *) 203 + val compress : 204 + level:int -> 205 + input:'a Eio.Flow.source -> 206 + output:'a Eio.Flow.sink -> 207 + unit 208 + end 209 + 210 + (** Data compression filters. *) 211 + module Compression : sig 212 + (** Gzip compression. 213 + 214 + @param level Compression level (1-9) 215 + @param input Data stream 216 + @param output Compressed stream *) 217 + val gzip : 218 + level:int -> 219 + input:'a Eio.Flow.source -> 220 + output:'a Eio.Flow.sink -> 221 + unit 222 + 223 + (** Brotli compression. 224 + 225 + @param level Compression level 226 + @param input Data stream 227 + @param output Compressed stream *) 228 + val brotli : 229 + level:int -> 230 + input:'a Eio.Flow.source -> 231 + output:'a Eio.Flow.sink -> 232 + unit 233 + 234 + (** Auto-detect and compress. 235 + 236 + @param preferred_formats Preferred compression formats 237 + @param accept_encoding Client Accept-Encoding header 238 + @param input Data stream 239 + @param output Compressed stream *) 240 + val auto_compress : 241 + preferred_formats:string list -> 242 + accept_encoding:string option -> 243 + input:'a Eio.Flow.source -> 244 + output:'a Eio.Flow.sink -> 245 + string option (** Returns content-encoding used *) 246 + end 247 + 248 + (** {1 Caching and Optimization} *) 249 + 250 + (** Check if content should be served from cache. 251 + 252 + @param metadata File metadata 253 + @param if_modified_since Client If-Modified-Since header 254 + @param if_none_match Client If-None-Match header 255 + @return True if content is not modified *) 256 + val check_not_modified : 257 + metadata:filter_metadata -> 258 + if_modified_since:string option -> 259 + if_none_match:string option -> 260 + bool 261 + 262 + (** Generate appropriate cache headers. 263 + 264 + @param metadata File metadata 265 + @param cache_policy Caching policy 266 + @return List of cache-related headers *) 267 + val generate_cache_headers : 268 + metadata:filter_metadata -> 269 + cache_policy:cache_policy -> 270 + (string * string) list 271 + 272 + (** {1 Streaming Operations} *) 273 + 274 + (** Stream processor for chunk-by-chunk filtering. *) 275 + type 'a stream_processor = { 276 + process_chunk : bytes -> bytes option; (** Process a data chunk *) 277 + finalize : unit -> bytes option; (** Finalize and get remaining data *) 278 + reset : unit -> unit; (** Reset processor state *) 279 + } 280 + 281 + (** Create a streaming filter. 282 + 283 + @param processor Stream processor 284 + @param input Source stream 285 + @param output Target stream *) 286 + val streaming_filter : 287 + processor:'a stream_processor -> 288 + input:'a Eio.Flow.source -> 289 + output:'a Eio.Flow.sink -> 290 + unit 291 + 292 + (** Chain multiple filters together. 293 + 294 + @param filters List of filter functions 295 + @param input Source stream 296 + @param output Target stream *) 297 + val chain_filters : 298 + filters:(('a Eio.Flow.source -> 'a Eio.Flow.sink -> unit) list) -> 299 + input:'a Eio.Flow.source -> 300 + output:'a Eio.Flow.sink -> 301 + unit 302 + 303 + (** {1 Error Handling} *) 304 + 305 + (** Filter-specific errors. *) 306 + type filter_error = 307 + | Data_corruption of string (** Data corruption detected *) 308 + | Unsupported_format of string (** Unsupported file format *) 309 + | Processing_failed of string (** Filter processing failed *) 310 + | Resource_exhausted of string (** Out of memory/disk space *) 311 + 312 + (** Filter exception. *) 313 + exception Filter_error of filter_error 314 + 315 + (** Convert filter error to string. *) 316 + val filter_error_to_string : filter_error -> string 317 + 318 + (** Safe filter wrapper that handles errors gracefully. 319 + 320 + @param fallback Fallback function if filter fails 321 + @param filter Primary filter function 322 + @param input Source stream 323 + @param output Target stream *) 324 + val safe_filter : 325 + fallback:('a Eio.Flow.source -> 'a Eio.Flow.sink -> unit) -> 326 + filter:('a Eio.Flow.source -> 'a Eio.Flow.sink -> unit) -> 327 + input:'a Eio.Flow.source -> 328 + output:'a Eio.Flow.sink -> 329 + unit
+414
lib/fastcgi_protocol.mli
··· 1 + (** FastCGI wire protocol parsing and serialization. 2 + 3 + This module handles the low-level FastCGI protocol details including 4 + record parsing, name-value pair encoding, and binary data serialization 5 + using Eio's Buf_read and Buf_write modules. 6 + 7 + The FastCGI protocol uses a binary record format where all data is 8 + transmitted as 8-byte fixed headers followed by variable-length content 9 + and optional padding. Multi-byte integers use network byte order for 10 + platform independence. 11 + 12 + The protocol supports several key features: 13 + - Request multiplexing over single connections 14 + - Variable-length encoding for efficient name-value pairs 15 + - Stream-based data transmission with proper termination 16 + - Alignment padding for optimal performance 17 + 18 + This module provides the low-level primitives for encoding and decoding 19 + these protocol elements, allowing higher-level modules to focus on 20 + application logic rather than binary protocol details. *) 21 + 22 + (** Protocol parsing error. 23 + 24 + Raised when invalid or malformed protocol data is encountered during 25 + parsing operations. This includes version mismatches, invalid record 26 + structures, malformed length encodings, and other protocol violations. *) 27 + exception Protocol_error of string 28 + 29 + (** {1 Protocol Parsing} 30 + 31 + These functions parse incoming FastCGI records and protocol elements 32 + from binary data streams. They validate protocol compliance and convert 33 + binary data into OCaml types for processing. *) 34 + 35 + (** Parse a FastCGI record header from a buffer. 36 + 37 + Reads exactly 8 bytes from the buffer to construct a record header. 38 + The header contains version, record type, request ID, content length, 39 + and padding length fields using network byte order. 40 + 41 + The function validates that the version is supported (currently only 42 + version 1) and that the record type is recognized. 43 + 44 + @param buf Input buffer positioned at the start of a record header 45 + @return Parsed record header with validated fields 46 + @raise Protocol_error if version is unsupported or data is malformed *) 47 + val parse_record_header : Eio.Buf_read.t -> Fastcgi_types.record_header 48 + 49 + (** Parse a complete FastCGI record from a buffer. 50 + 51 + Reads a record header followed by the specified amount of content data 52 + and padding. This is the primary function for reading FastCGI records 53 + from network streams. 54 + 55 + The function ensures that exactly the number of content and padding 56 + bytes specified in the header are read, maintaining proper stream 57 + alignment for subsequent records. 58 + 59 + @param buf Input buffer positioned at the start of a complete record 60 + @return Complete parsed record with header, content, and optional padding 61 + @raise Protocol_error if the record structure is invalid *) 62 + val parse_record : Eio.Buf_read.t -> Fastcgi_types.record 63 + 64 + (** Parse begin request body from record content. 65 + 66 + Extracts role and connection flags from the 8-byte Begin_request record 67 + body. The role indicates whether the application should act as a 68 + Responder, Authorizer, or Filter. The flags control connection lifetime 69 + management. 70 + 71 + @param content Record content bytes (must be exactly 8 bytes) 72 + @return Begin request body with role and flags 73 + @raise Protocol_error if content length is wrong or role is unknown *) 74 + val parse_begin_request : bytes -> Fastcgi_types.begin_request_body 75 + 76 + (** Parse end request body from record content. 77 + 78 + Extracts application status and protocol status from the 8-byte 79 + End_request record body. The application status is similar to a 80 + program exit code, while protocol status indicates completion 81 + or rejection reasons. 82 + 83 + @param content Record content bytes (must be exactly 8 bytes) 84 + @return End request body with status codes 85 + @raise Protocol_error if content length is wrong or status is invalid *) 86 + val parse_end_request : bytes -> Fastcgi_types.end_request_body 87 + 88 + (** Parse name-value pairs from record content. 89 + 90 + Decodes the compact binary encoding used for parameter transmission. 91 + Names and values can be up to 127 bytes (1-byte length) or longer 92 + (4-byte length with high bit set). This encoding allows efficient 93 + transmission of CGI environment variables and other parameters. 94 + 95 + @param content Record content bytes containing encoded name-value pairs 96 + @return List of decoded name-value pairs 97 + @raise Protocol_error if the encoding is malformed *) 98 + val parse_name_value_pairs : bytes -> Fastcgi_types.name_value_pair list 99 + 100 + (** {1 Protocol Serialization} 101 + 102 + These functions serialize OCaml types into the binary FastCGI protocol 103 + format for transmission to web servers. All multi-byte integers are 104 + written in network byte order for platform independence. *) 105 + 106 + (** Write a FastCGI record header to a buffer. 107 + 108 + Serializes a record header into exactly 8 bytes using network byte order. 109 + The header format is: version (1 byte), type (1 byte), request ID (2 bytes), 110 + content length (2 bytes), padding length (1 byte), reserved (1 byte). 111 + 112 + @param buf Output buffer to write the header to 113 + @param header Record header to serialize *) 114 + val write_record_header : Eio.Buf_write.t -> Fastcgi_types.record_header -> unit 115 + 116 + (** Write a complete FastCGI record to a buffer. 117 + 118 + Serializes a complete record including header, content data, and padding. 119 + This is the primary function for sending FastCGI records over network 120 + connections. The function ensures proper alignment by writing any 121 + specified padding bytes. 122 + 123 + @param buf Output buffer to write the complete record to 124 + @param record Complete record with header, content, and optional padding *) 125 + val write_record : Eio.Buf_write.t -> Fastcgi_types.record -> unit 126 + 127 + (** Write begin request body to bytes. 128 + 129 + Serializes role and connection flags into the 8-byte Begin_request record 130 + body format. The first 2 bytes contain the role, the next byte contains 131 + flags, and the remaining 5 bytes are reserved (set to zero). 132 + 133 + @param body Begin request body with role and flags 134 + @return 8-byte serialized record body *) 135 + val write_begin_request : Fastcgi_types.begin_request_body -> bytes 136 + 137 + (** Write end request body to bytes. 138 + 139 + Serializes application and protocol status into the 8-byte End_request 140 + record body format. The first 4 bytes contain the application status, 141 + the next byte contains the protocol status, and the remaining 3 bytes 142 + are reserved. 143 + 144 + @param body End request body with status codes 145 + @return 8-byte serialized record body *) 146 + val write_end_request : Fastcgi_types.end_request_body -> bytes 147 + 148 + (** Write name-value pairs to bytes. 149 + 150 + Serializes name-value pairs using the compact binary encoding where 151 + each pair is encoded as: name length, value length, name data, value data. 152 + Lengths up to 127 bytes use 1-byte encoding; longer lengths use 4-byte 153 + encoding with the high bit set. 154 + 155 + @param pairs List of name-value pairs to encode 156 + @return Serialized bytes containing all encoded pairs *) 157 + val write_name_value_pairs : Fastcgi_types.name_value_pair list -> bytes 158 + 159 + (** {1 Type Conversions} *) 160 + 161 + (** Convert record type to integer. *) 162 + val record_type_to_int : Fastcgi_types.record_type -> int 163 + 164 + (** Convert integer to record type. 165 + 166 + @param i Integer value 167 + @return Record type 168 + @raise Protocol_error if unknown *) 169 + val record_type_of_int : int -> Fastcgi_types.record_type 170 + 171 + (** Convert role to integer. *) 172 + val role_to_int : Fastcgi_types.role -> int 173 + 174 + (** Convert integer to role. 175 + 176 + @param i Integer value 177 + @return Role 178 + @raise Protocol_error if unknown *) 179 + val role_of_int : int -> Fastcgi_types.role 180 + 181 + (** Convert protocol status to integer. *) 182 + val protocol_status_to_int : Fastcgi_types.protocol_status -> int 183 + 184 + (** Convert integer to protocol status. 185 + 186 + @param i Integer value 187 + @return Protocol status 188 + @raise Protocol_error if unknown *) 189 + val protocol_status_of_int : int -> Fastcgi_types.protocol_status 190 + 191 + (** {1 Length Encoding} 192 + 193 + FastCGI uses a variable-length encoding for efficient transmission of 194 + length values in name-value pairs. This encoding minimizes overhead 195 + for short strings while supporting arbitrarily long values. *) 196 + 197 + (** Encode a length value using FastCGI variable-length encoding. 198 + 199 + Short lengths (0-127) are encoded in a single byte with the high bit 200 + clear. Longer lengths (128 and above) are encoded in 4 bytes with the 201 + high bit of the first byte set to 1, and the remaining 31 bits containing 202 + the actual length value. 203 + 204 + This encoding provides optimal space efficiency for typical use cases 205 + where most parameter names and values are relatively short. 206 + 207 + @param length Length value to encode (must be non-negative) 208 + @return 1-byte or 4-byte encoded length 209 + @raise Invalid_argument if length is negative *) 210 + val encode_length : int -> bytes 211 + 212 + (** Decode a length value from FastCGI variable-length encoding. 213 + 214 + Reads either 1 or 4 bytes from the buffer depending on the high bit 215 + of the first byte. Returns both the decoded length and the number of 216 + bytes consumed to allow proper buffer advancement. 217 + 218 + @param buf Input buffer positioned at the start of an encoded length 219 + @return Tuple of (decoded length, bytes consumed) 220 + @raise Protocol_error if the encoding is invalid or buffer is too short *) 221 + val decode_length : Eio.Buf_read.t -> int * int 222 + 223 + (** {1 Record Construction} 224 + 225 + These convenience functions create properly formatted FastCGI records 226 + with correct headers and content. They handle the binary encoding details 227 + and ensure protocol compliance. *) 228 + 229 + (** Create a begin request record. 230 + 231 + Constructs a Begin_request record to initiate a new FastCGI request. 232 + This record type is sent by web servers to start request processing 233 + and specifies the role the application should play. 234 + 235 + The record contains the application role (Responder, Authorizer, or Filter) 236 + and connection flags that control whether the connection should be kept 237 + alive after the request completes. 238 + 239 + @param request_id Unique request identifier for multiplexing 240 + @param role Role the application should play for this request 241 + @param flags Connection management flags 242 + @return Complete Begin_request record ready for transmission *) 243 + val make_begin_request : 244 + request_id:Fastcgi_types.request_id -> 245 + role:Fastcgi_types.role -> 246 + flags:Fastcgi_types.connection_flags -> 247 + Fastcgi_types.record 248 + 249 + (** Create an end request record. 250 + 251 + Constructs an End_request record to complete a FastCGI request. 252 + This record is sent by applications to indicate request completion 253 + and provide both application-level and protocol-level status information. 254 + 255 + The application status is similar to a program exit code, where 0 256 + indicates success and non-zero values indicate errors. The protocol 257 + status indicates whether the request was completed normally or rejected 258 + for protocol-related reasons. 259 + 260 + @param request_id Request ID that is being completed 261 + @param app_status Application exit status (0 for success) 262 + @param protocol_status Protocol completion status 263 + @return Complete End_request record ready for transmission *) 264 + val make_end_request : 265 + request_id:Fastcgi_types.request_id -> 266 + app_status:Fastcgi_types.app_status -> 267 + protocol_status:Fastcgi_types.protocol_status -> 268 + Fastcgi_types.record 269 + 270 + (** Create a params record. 271 + 272 + @param request_id Request ID 273 + @param params Parameter name-value pairs 274 + @return Params record *) 275 + val make_params_record : 276 + request_id:Fastcgi_types.request_id -> 277 + params:(string * string) list -> 278 + Fastcgi_types.record 279 + 280 + (** Create a stream record (stdin, stdout, stderr, data). 281 + 282 + @param record_type Stream record type 283 + @param request_id Request ID 284 + @param data Stream data 285 + @return Stream record *) 286 + val make_stream_record : 287 + record_type:Fastcgi_types.record_type -> 288 + request_id:Fastcgi_types.request_id -> 289 + data:bytes -> 290 + Fastcgi_types.record 291 + 292 + (** Create an empty stream record (marks end of stream). 293 + 294 + @param record_type Stream record type 295 + @param request_id Request ID 296 + @return Empty stream record *) 297 + val make_empty_stream_record : 298 + record_type:Fastcgi_types.record_type -> 299 + request_id:Fastcgi_types.request_id -> 300 + Fastcgi_types.record 301 + 302 + (** Create a get values record. 303 + 304 + @param variables Variable names to query 305 + @return Get values record *) 306 + val make_get_values_record : 307 + variables:string list -> 308 + Fastcgi_types.record 309 + 310 + (** Create a get values result record. 311 + 312 + @param values Variable name-value pairs 313 + @return Get values result record *) 314 + val make_get_values_result_record : 315 + values:(string * string) list -> 316 + Fastcgi_types.record 317 + 318 + (** Create an unknown type record. 319 + 320 + @param unknown_type Unknown record type value 321 + @return Unknown type record *) 322 + val make_unknown_type_record : 323 + unknown_type:int -> 324 + Fastcgi_types.record 325 + 326 + (** Create an abort request record. 327 + 328 + @param request_id Request ID to abort 329 + @return Abort request record *) 330 + val make_abort_request_record : 331 + request_id:Fastcgi_types.request_id -> 332 + Fastcgi_types.record 333 + 334 + (** {1 Validation} 335 + 336 + These functions validate protocol elements for compliance with FastCGI 337 + requirements. They help detect malformed data and ensure protocol 338 + correctness during parsing and construction. *) 339 + 340 + (** Validate a record header. 341 + 342 + Checks that a record header contains valid values for all fields. 343 + This includes verifying the protocol version, record type bounds, 344 + content length limits, and padding length constraints. 345 + 346 + @param header Record header to validate 347 + @return True if the header is valid and protocol-compliant 348 + @raise Protocol_error if any field contains invalid values *) 349 + val validate_record_header : Fastcgi_types.record_header -> bool 350 + 351 + (** Validate a complete record. 352 + 353 + Performs comprehensive validation of a complete record including 354 + header validation and content/padding length consistency checks. 355 + Ensures the record can be safely transmitted or processed. 356 + 357 + @param record Complete record to validate 358 + @return True if the entire record is valid and well-formed 359 + @raise Protocol_error if any part of the record is invalid *) 360 + val validate_record : Fastcgi_types.record -> bool 361 + 362 + (** Check if a record type is a management record. 363 + 364 + Management records use request ID 0 and contain protocol-level information 365 + such as capability queries (Get_values) and unknown type responses. 366 + They are not associated with any specific request. 367 + 368 + @param record_type Record type to classify 369 + @return True if this is a management record type *) 370 + val is_management_record : Fastcgi_types.record_type -> bool 371 + 372 + (** Check if a record type is a stream record. 373 + 374 + Stream records (Params, Stdin, Stdout, Stderr, Data) can be sent in 375 + multiple parts and are terminated with an empty record of the same type. 376 + This allows streaming of arbitrarily large data without buffering. 377 + 378 + @param record_type Record type to classify 379 + @return True if this is a stream record type *) 380 + val is_stream_record : Fastcgi_types.record_type -> bool 381 + 382 + (** {1 Protocol Constants} 383 + 384 + Essential constants and utility functions for FastCGI protocol 385 + implementation. These values are defined by the protocol specification. *) 386 + 387 + (** Null request ID for management records. 388 + 389 + Management records always use request ID 0 to indicate they are not 390 + associated with any specific request. Applications must use non-zero 391 + request IDs for all application records. *) 392 + val null_request_id : Fastcgi_types.request_id 393 + 394 + (** Maximum content length for a single record. 395 + 396 + FastCGI records can contain at most 65535 bytes of content data. 397 + Larger data must be split across multiple records of the same type. *) 398 + val max_content_length : int 399 + 400 + (** Maximum padding length for a record. 401 + 402 + Records can have at most 255 bytes of padding for alignment purposes. 403 + Padding bytes are ignored by the receiver. *) 404 + val max_padding_length : int 405 + 406 + (** Calculate optimal padding for 8-byte alignment. 407 + 408 + Computes the number of padding bytes needed to align the total record 409 + size to an 8-byte boundary. This provides optimal performance on most 410 + architectures by ensuring proper memory alignment. 411 + 412 + @param content_length Length of the record content data 413 + @return Number of padding bytes needed (0-7) *) 414 + val calculate_padding : int -> int
+222
lib/fastcgi_responder.mli
··· 1 + (** Responder role implementation for FastCGI. 2 + 3 + The Responder role is the most common FastCGI role, equivalent to 4 + traditional CGI applications. It handles HTTP requests and generates 5 + HTTP responses. 6 + 7 + A Responder FastCGI application has the same purpose as a CGI/1.1 program: 8 + it receives all the information associated with an HTTP request and generates 9 + an HTTP response. This includes CGI environment variables, request headers, 10 + request body data, and produces HTTP response headers and body content. 11 + 12 + The key difference from traditional CGI is that Responder applications are 13 + long-lived processes that can handle multiple requests efficiently, avoiding 14 + the overhead of process creation for each request. 15 + 16 + This module provides high-level abstractions for working with HTTP requests 17 + and responses, automatically handling the conversion between FastCGI protocol 18 + elements and familiar HTTP concepts. *) 19 + 20 + (** {1 HTTP Request/Response Types} *) 21 + 22 + (** CGI-style environment variables. 23 + 24 + A list of name-value pairs containing the CGI environment variables 25 + passed from the web server. These typically include variables like 26 + REQUEST_METHOD, REQUEST_URI, HTTP_HOST, CONTENT_TYPE, etc. *) 27 + type cgi_env = (string * string) list 28 + 29 + (** HTTP request information extracted from FastCGI parameters. 30 + 31 + This type represents an HTTP request in a convenient form for application 32 + processing. It extracts and parses the most commonly needed information 33 + from the CGI environment variables provided by the web server. *) 34 + type 'a http_request = { 35 + method_ : string; (** HTTP method (GET, POST, PUT, DELETE, etc.). 36 + Extracted from REQUEST_METHOD CGI variable. *) 37 + uri : string; (** Request URI path component, without query string. 38 + Extracted from REQUEST_URI or SCRIPT_NAME + PATH_INFO. *) 39 + query_string : string; (** URL query string parameters (after the '?' in the URL). 40 + Extracted from QUERY_STRING CGI variable. *) 41 + content_type : string option; (** MIME type of the request body, if present. 42 + Extracted from CONTENT_TYPE CGI variable. *) 43 + content_length : int option; (** Length of the request body in bytes, if known. 44 + Extracted from CONTENT_LENGTH CGI variable. *) 45 + headers : (string * string) list; (** HTTP headers sent by the client. Extracted from 46 + CGI variables with HTTP_ prefix. *) 47 + body : 'a Eio.Flow.source; (** Request body data stream. For POST requests, 48 + this contains form data or payload content. *) 49 + } 50 + 51 + (** HTTP response builder for constructing responses. 52 + 53 + This type provides a streaming interface for generating HTTP responses. 54 + It handles proper HTTP formatting including status line, headers, and 55 + body content. The response is written incrementally to avoid buffering 56 + large responses in memory. *) 57 + type 'a http_response = { 58 + write_status : int -> unit; (** Set the HTTP status code (200, 404, 500, etc.). 59 + Must be called before writing headers or body. *) 60 + write_header : string -> string -> unit; (** Add an HTTP response header. 61 + Common headers include Content-Type, Set-Cookie, etc. *) 62 + write_body : string -> unit; (** Write string content to the response body. 63 + Handles encoding and streaming automatically. *) 64 + write_body_chunk : bytes -> unit; (** Write binary data to the response body. 65 + Useful for file downloads or binary content. *) 66 + finish : unit -> unit; (** Complete the response and close the connection. 67 + Must be called to ensure proper termination. *) 68 + } 69 + 70 + (** {1 Conversion Functions} *) 71 + 72 + (** Convert FastCGI request to HTTP request. 73 + 74 + Extracts HTTP-specific information from FastCGI parameters 75 + and creates an HTTP request object. 76 + 77 + @param request FastCGI request 78 + @return HTTP request with extracted information *) 79 + val request_of_fastcgi : 'a Fastcgi_types.request -> 'a http_request 80 + 81 + (** Create HTTP response writer from FastCGI response. 82 + 83 + Wraps FastCGI response streams to provide HTTP-style 84 + response writing interface. 85 + 86 + @param response FastCGI response 87 + @return HTTP response writer *) 88 + val response_of_fastcgi : 'a Fastcgi_types.response -> 'a http_response 89 + 90 + (** {1 Handler Utilities} *) 91 + 92 + (** Responder handler type. *) 93 + type 'a responder_handler = 'a Fastcgi_types.request -> 'a Fastcgi_types.response -> Fastcgi_types.response_result 94 + 95 + (** Convenience handler wrapper for HTTP-style handlers. 96 + 97 + Converts an HTTP-style handler function into a FastCGI handler. 98 + This allows writing handlers that work with HTTP request/response 99 + objects instead of raw FastCGI types. 100 + 101 + @param handler HTTP handler function 102 + @return FastCGI responder handler *) 103 + val http_handler : 104 + ('a http_request -> 'a http_response -> unit) -> 105 + 'a responder_handler 106 + 107 + (** {1 Common HTTP Operations} *) 108 + 109 + (** Send a simple text response. 110 + 111 + @param response HTTP response writer 112 + @param status HTTP status code 113 + @param content_type MIME type 114 + @param body Response body text *) 115 + val send_text_response : 116 + 'a http_response -> 117 + status:int -> 118 + content_type:string -> 119 + body:string -> 120 + unit 121 + 122 + (** Send a JSON response. 123 + 124 + @param response HTTP response writer 125 + @param status HTTP status code 126 + @param json JSON string *) 127 + val send_json_response : 128 + 'a http_response -> 129 + status:int -> 130 + json:string -> 131 + unit 132 + 133 + (** Send an HTML response. 134 + 135 + @param response HTTP response writer 136 + @param status HTTP status code 137 + @param html HTML content *) 138 + val send_html_response : 139 + 'a http_response -> 140 + status:int -> 141 + html:string -> 142 + unit 143 + 144 + (** Send an error response. 145 + 146 + @param response HTTP response writer 147 + @param status HTTP error status code 148 + @param message Error message *) 149 + val send_error_response : 150 + 'a http_response -> 151 + status:int -> 152 + message:string -> 153 + unit 154 + 155 + (** Send a redirect response. 156 + 157 + @param response HTTP response writer 158 + @param status Redirect status code (301, 302, etc.) 159 + @param location Target URL *) 160 + val send_redirect_response : 161 + 'a http_response -> 162 + status:int -> 163 + location:string -> 164 + unit 165 + 166 + (** {1 Request Parsing} *) 167 + 168 + (** Parse query string into parameter map. 169 + 170 + @param query_string URL-encoded query string 171 + @return Association list of parameter name-value pairs *) 172 + val parse_query_string : string -> (string * string) list 173 + 174 + (** Parse form data from request body. 175 + 176 + Supports both application/x-www-form-urlencoded and 177 + multipart/form-data content types. 178 + 179 + @param request HTTP request 180 + @return Association list of form field name-value pairs *) 181 + val parse_form_data : 'a http_request -> (string * string) list 182 + 183 + (** Get request header value. 184 + 185 + @param request HTTP request 186 + @param name Header name (case-insensitive) 187 + @return Header value if present *) 188 + val get_header : 'a http_request -> string -> string option 189 + 190 + (** Get request parameter from query string or form data. 191 + 192 + @param request HTTP request 193 + @param name Parameter name 194 + @return Parameter value if present *) 195 + val get_param : 'a http_request -> string -> string option 196 + 197 + (** {1 File Operations} *) 198 + 199 + (** File upload information. *) 200 + type 'a file_upload = { 201 + filename : string option; (** Original filename *) 202 + content_type : string option; (** MIME type *) 203 + size : int; (** File size in bytes *) 204 + data : 'a Eio.Flow.source; (** File content stream *) 205 + } 206 + 207 + (** Parse file uploads from multipart form data. 208 + 209 + @param request HTTP request with multipart content 210 + @return Association list of field name to file upload *) 211 + val parse_file_uploads : 'a http_request -> (string * 'a file_upload) list 212 + 213 + (** Save uploaded file to filesystem. 214 + 215 + @param fs Filesystem capability 216 + @param path Destination path 217 + @param upload File upload to save *) 218 + val save_upload : 219 + fs:Eio.Fs.dir_ty Eio.Path.t -> 220 + path:string -> 221 + upload:'a file_upload -> 222 + unit
+444
lib/fastcgi_types.mli
··· 1 + (** Core FastCGI types and constants. 2 + 3 + This module defines the fundamental types used throughout the 4 + FastCGI protocol implementation. 5 + 6 + FastCGI is an open extension to CGI that provides high performance for 7 + all Internet applications without the penalties of Web server APIs. 8 + Unlike traditional CGI programs that are started for each request, 9 + FastCGI applications are long-lived processes that can handle multiple 10 + requests over persistent connections. *) 11 + 12 + (** {1 Core Types} *) 13 + 14 + (** FastCGI protocol version. 15 + 16 + The current protocol uses version 1. Future versions of the 17 + protocol may increment this value. Applications should check the version 18 + field in incoming records and reject unsupported versions. 19 + 20 + Version 1 is represented by the value [1]. *) 21 + type version = int 22 + 23 + (** FastCGI record types. 24 + 25 + All data transmitted over a FastCGI connection is packaged in records. 26 + Each record has a type that determines how the record's content should 27 + be interpreted. The protocol defines both management records (for 28 + protocol-level communication) and application records (for request 29 + processing). 30 + 31 + Management records contain information that is not specific to any web 32 + server request, such as capability queries and unknown type responses. 33 + Application records contain information about a particular request, 34 + identified by a non-zero request ID. *) 35 + type record_type = 36 + | Begin_request (** Starts a new request. Sent by the web server to begin 37 + processing. Contains the role and connection flags. *) 38 + | Abort_request (** Aborts an existing request. Sent by the web server 39 + when an HTTP client closes its connection while the 40 + request is still being processed. *) 41 + | End_request (** Completes a request. Sent by the application to 42 + terminate processing, either normally or due to 43 + an error condition. *) 44 + | Params (** Parameter name-value pairs. Used to transmit CGI-style 45 + environment variables from the web server to the 46 + application. Sent as a stream. *) 47 + | Stdin (** Standard input data. Contains the request body data 48 + that would normally be available on stdin in CGI. 49 + Sent as a stream. *) 50 + | Stdout (** Standard output data. Response data from the application 51 + to the web server. This becomes the HTTP response. 52 + Sent as a stream. *) 53 + | Stderr (** Standard error data. Error messages from the application. 54 + Used for logging and debugging. Sent as a stream. *) 55 + | Data (** Additional data stream. Used only in the Filter role 56 + to transmit file data that needs to be filtered. 57 + Sent as a stream. *) 58 + | Get_values (** Management record to query application variables. 59 + Allows the web server to discover application 60 + capabilities like max connections and multiplexing. *) 61 + | Get_values_result (** Management record response to Get_values. Contains 62 + the requested variable values. *) 63 + | Unknown_type (** Management record for unknown type handling. Sent by 64 + the application when it receives a record type it 65 + doesn't understand. *) 66 + 67 + (** FastCGI application roles. 68 + 69 + A FastCGI application can play one of several well-defined roles. 70 + The role determines what information the application receives and 71 + what it's expected to produce. 72 + 73 + A FastCGI application plays one of several well-defined roles. The most 74 + familiar is the Responder role, in which the application receives all 75 + the information associated with an HTTP request and generates an HTTP 76 + response. *) 77 + type role = 78 + | Responder (** The most common role, equivalent to traditional CGI. 79 + The application receives all information associated with 80 + an HTTP request and generates an HTTP response. This 81 + includes environment variables, request headers, and 82 + request body data. *) 83 + | Authorizer (** Performs access control decisions. The application 84 + receives HTTP request information and generates an 85 + authorized/unauthorized decision. In case of authorization, 86 + it can associate additional variables with the request. 87 + For unauthorized requests, it provides a complete HTTP 88 + error response. *) 89 + | Filter (** Processes data streams with filtering. The application 90 + receives HTTP request information plus an additional 91 + data stream from a file stored on the web server, and 92 + generates a "filtered" version of the data as an HTTP 93 + response. Both the file and the filter can be access 94 + controlled. *) 95 + 96 + (** Request ID for multiplexing multiple requests over a single connection. 97 + 98 + FastCGI supports multiplexing, allowing multiple concurrent requests 99 + to be processed over a single transport connection. Each request is 100 + identified by a unique request ID within the scope of that connection. 101 + 102 + The Web server re-uses FastCGI request IDs; the application keeps track 103 + of the current state of each request ID on a given transport connection. 104 + Request IDs should be small integers to allow efficient tracking using 105 + arrays rather than hash tables. 106 + 107 + The value [0] is reserved for management records and is called the 108 + "null request ID". *) 109 + type request_id = int 110 + 111 + (** Application-level status code. 112 + 113 + When an application completes a request, it provides an application 114 + status code similar to the exit status of a traditional CGI program. 115 + A value of [0] indicates success, while non-zero values indicate 116 + various error conditions. 117 + 118 + The application sets the appStatus component to the status code that 119 + the CGI program would have returned via the exit system call. *) 120 + type app_status = int 121 + 122 + (** Protocol-level status codes. 123 + 124 + In addition to application status, each request completion includes 125 + a protocol-level status that indicates whether the request was 126 + processed normally or rejected for protocol-related reasons. 127 + 128 + These status codes allow the web server to understand why a request 129 + was not processed and take appropriate action. *) 130 + type protocol_status = 131 + | Request_complete (** Normal end of request. The application successfully 132 + processed the request and the appStatus field 133 + indicates the application-level result. *) 134 + | Cant_mpx_conn (** Rejecting a new request because the application 135 + cannot multiplex connections. This happens when 136 + a web server sends concurrent requests over one 137 + connection to an application that processes only 138 + one request at a time per connection. *) 139 + | Overloaded (** Rejecting a new request because the application 140 + is overloaded. This occurs when the application 141 + runs out of some resource, such as database 142 + connections or memory. *) 143 + | Unknown_role (** Rejecting a new request because the requested 144 + role is unknown to the application. This happens 145 + when the web server specifies a role that the 146 + application doesn't implement. *) 147 + 148 + (** Connection flags for controlling connection behavior. 149 + 150 + These flags are sent in Begin_request records to control how the 151 + connection should be managed after the request completes. *) 152 + type connection_flags = { 153 + keep_conn : bool; (** Keep connection open after request completion. 154 + 155 + If false, the application closes the connection after 156 + responding to this request. If true, the application 157 + does not close the connection after responding to this 158 + request; the Web server retains responsibility for the 159 + connection. 160 + 161 + This flag enables connection reuse for better performance, 162 + especially important for high-traffic applications. *) 163 + } 164 + 165 + (** {1 Record Types} *) 166 + 167 + (** FastCGI record header. 168 + 169 + Every FastCGI record begins with an 8-byte header that identifies 170 + the record type, request ID, and content length. This fixed-length 171 + prefix allows efficient parsing and proper demultiplexing of records. 172 + 173 + A FastCGI record consists of a fixed-length prefix followed by a 174 + variable number of content and padding bytes. 175 + 176 + The header format is platform-independent and uses network byte order 177 + for multi-byte integers. *) 178 + type record_header = { 179 + version : int; (** Protocol version. Must be [1] for this specification. 180 + Future versions may increment this value. *) 181 + record_type : record_type; (** Type of this record, determining how to interpret 182 + the content data. *) 183 + request_id : request_id; (** Request ID this record belongs to. Value [0] is 184 + reserved for management records. *) 185 + content_length : int; (** Number of bytes in the content data. Must be 186 + between [0] and [65535]. *) 187 + padding_length : int; (** Number of padding bytes following content. 188 + Must be between [0] and [255]. Used for alignment. *) 189 + } 190 + 191 + (** Begin request record body. 192 + 193 + This record marks the start of a new request and specifies the role 194 + the application should play and connection management flags. 195 + 196 + The Web server sends a FCGI_BEGIN_REQUEST record to start a request. 197 + The record body contains the role and flags that control request 198 + processing. *) 199 + type begin_request_body = { 200 + role : role; (** The role the web server expects the application 201 + to play for this request. *) 202 + flags : connection_flags; (** Flags controlling connection behavior after 203 + request completion. *) 204 + } 205 + 206 + (** End request record body. 207 + 208 + This record marks the completion of a request and provides both 209 + application-level and protocol-level status information. 210 + 211 + The application sends a FCGI_END_REQUEST record to terminate a request, 212 + either because the application has processed the request or because the 213 + application has rejected the request. *) 214 + type end_request_body = { 215 + app_status : app_status; (** Application-level status code, similar to 216 + a CGI program's exit status. *) 217 + protocol_status : protocol_status; (** Protocol-level status indicating normal 218 + completion or rejection reason. *) 219 + } 220 + 221 + (** Complete FastCGI record. 222 + 223 + A complete record consists of the header, content data, and optional 224 + padding. The content interpretation depends on the record type. 225 + 226 + Records support padding to allow senders to keep data aligned for more 227 + efficient processing. Experience with the X window system protocols shows 228 + the performance benefit of such alignment. *) 229 + type record = { 230 + header : record_header; (** Fixed 8-byte header with record metadata. *) 231 + content : bytes; (** Variable-length content data. Length must match 232 + header.content_length. *) 233 + padding : bytes option; (** Optional padding data for alignment. Length must 234 + match header.padding_length if present. *) 235 + } 236 + 237 + (** Name-value pair for parameters. 238 + 239 + FastCGI uses a compact binary encoding for transmitting name-value pairs 240 + such as CGI environment variables. This encoding supports both short 241 + and long names/values efficiently. 242 + 243 + FastCGI transmits a name-value pair as the length of the name, followed 244 + by the length of the value, followed by the name, followed by the value. 245 + Lengths of 127 bytes and less can be encoded in one byte, while longer 246 + lengths are always encoded in four bytes. *) 247 + type name_value_pair = { 248 + name : string; (** Parameter name. For CGI compatibility, these are typically 249 + uppercase environment variable names like "REQUEST_METHOD". *) 250 + value : string; (** Parameter value. The value does not include a terminating 251 + null byte in the FastCGI encoding. *) 252 + } 253 + 254 + (** {1 Request/Response Model} *) 255 + 256 + (** Request context containing all information for a FastCGI request. 257 + 258 + This high-level type aggregates all the information needed to process 259 + a FastCGI request. It combines the protocol-level details (request ID, 260 + role, flags) with the application data (parameters and input streams). 261 + 262 + The request follows a two-level processing model: First, the protocol 263 + multiplexes a single transport connection between several independent 264 + FastCGI requests. Second, within each request the protocol provides 265 + several independent data streams in each direction. *) 266 + type 'a request = { 267 + request_id : request_id; (** Unique identifier for this request within 268 + the connection scope. Used for multiplexing. *) 269 + role : role; (** The role this application should play for 270 + this request (Responder, Authorizer, or Filter). *) 271 + flags : connection_flags; (** Connection management flags from the web server. *) 272 + params : (string * string) list; (** CGI-style environment variables transmitted 273 + via FCGI_PARAMS records. These provide request 274 + context like HTTP headers, server info, etc. *) 275 + stdin : 'a Eio.Flow.source; (** Standard input stream, containing request body 276 + data (equivalent to CGI stdin). For HTTP POST 277 + requests, this contains the form data or payload. *) 278 + data : 'a Eio.Flow.source option; (** Additional data stream, used only in Filter 279 + role. Contains file data that needs to be 280 + filtered. [None] for Responder and Authorizer. *) 281 + } 282 + 283 + (** Response builder for constructing FastCGI responses. 284 + 285 + This type provides the output streams for sending response data back 286 + to the web server. Following CGI conventions, it separates normal 287 + output from error output. 288 + 289 + Both stdout and stderr data pass over a single transport connection from 290 + the application to the Web server, rather than requiring separate pipes 291 + as with CGI/1.1. *) 292 + type 'a response = { 293 + stdout : 'a Eio.Flow.sink; (** Standard output stream for response data. 294 + In Responder role, this contains the HTTP 295 + response including headers and body. *) 296 + stderr : 'a Eio.Flow.sink; (** Standard error stream for logging and debugging. 297 + All role protocols use the FCGI_STDERR stream 298 + just the way stderr is used in conventional 299 + applications programming: to report application-level 300 + errors in an intelligible way. *) 301 + } 302 + 303 + (** Complete response with status. 304 + 305 + When an application finishes processing a request, it must provide 306 + both application-level and protocol-level status information. This 307 + allows the web server to understand the outcome and take appropriate 308 + action. 309 + 310 + This corresponds to the FCGI_END_REQUEST record sent by the application. *) 311 + type response_result = { 312 + app_status : app_status; (** Application exit status, equivalent to what 313 + a CGI program would return via exit(). *) 314 + protocol_status : protocol_status; (** Protocol-level completion status, indicating 315 + normal completion or various rejection reasons. *) 316 + } 317 + 318 + (** {1 Protocol Constants} *) 319 + 320 + (** Protocol version constant. 321 + 322 + This constant represents FCGI_VERSION_1. This value should be used in 323 + the version field of all record headers. *) 324 + val version_1 : int 325 + 326 + (** Standard file descriptor for FastCGI listening socket. 327 + 328 + The Web server leaves a single file descriptor, FCGI_LISTENSOCK_FILENO, 329 + open when the application begins execution. This descriptor refers to a 330 + listening socket created by the Web server. 331 + 332 + The value equals STDIN_FILENO (0). Applications can distinguish between 333 + CGI and FastCGI invocation by calling getpeername() on this descriptor. *) 334 + val listensock_fileno : int 335 + 336 + (** {2 Record Type Constants} 337 + 338 + These integer constants correspond to the record_type variants and are 339 + used in the binary protocol encoding. These are the values transmitted 340 + in the type field of record headers. *) 341 + 342 + (** Value [1]. Starts a new request. *) 343 + val fcgi_begin_request : int 344 + 345 + (** Value [2]. Aborts an existing request. *) 346 + val fcgi_abort_request : int 347 + 348 + (** Value [3]. Completes a request. *) 349 + val fcgi_end_request : int 350 + 351 + (** Value [4]. Parameter name-value pairs. *) 352 + val fcgi_params : int 353 + 354 + (** Value [5]. Standard input data. *) 355 + val fcgi_stdin : int 356 + 357 + (** Value [6]. Standard output data. *) 358 + val fcgi_stdout : int 359 + 360 + (** Value [7]. Standard error data. *) 361 + val fcgi_stderr : int 362 + 363 + (** Value [8]. Additional data stream (Filter). *) 364 + val fcgi_data : int 365 + 366 + (** Value [9]. Query application variables. *) 367 + val fcgi_get_values : int 368 + 369 + (** Value [10]. Response to Get_values. *) 370 + val fcgi_get_values_result : int 371 + 372 + (** Value [11]. Unknown record type response. *) 373 + val fcgi_unknown_type : int 374 + 375 + (** {2 Role Constants} 376 + 377 + These integer constants correspond to the role variants and are used 378 + in Begin_request record bodies. These identify the role the web server 379 + expects the application to play. *) 380 + 381 + (** Value [1]. Handle HTTP requests and generate responses. *) 382 + val fcgi_responder : int 383 + 384 + (** Value [2]. Perform authorization decisions. *) 385 + val fcgi_authorizer : int 386 + 387 + (** Value [3]. Process data streams with filtering. *) 388 + val fcgi_filter : int 389 + 390 + (** {2 Flag Constants} 391 + 392 + These constants are used in the flags field of Begin_request records 393 + to control connection behavior. *) 394 + 395 + (** Value [1]. Keep connection open after request. 396 + If zero, the application closes the connection after 397 + responding to this request. If not zero, the application 398 + does not close the connection after responding to this 399 + request. *) 400 + val fcgi_keep_conn : int 401 + 402 + (** {2 Protocol Limits} 403 + 404 + These constants define the maximum sizes for various protocol elements, 405 + ensuring compatibility and preventing buffer overflows. *) 406 + 407 + (** Value [65535]. Maximum bytes in record content. 408 + Between 0 and 65535 bytes of data, interpreted 409 + according to the record type. *) 410 + val max_content_length : int 411 + 412 + (** Value [255]. Maximum bytes in record padding. 413 + Between 0 and 255 bytes of data, which are ignored. *) 414 + val max_padding_length : int 415 + 416 + (** Value [8]. Fixed size of record headers. 417 + Number of bytes in a FCGI_Header. Future versions 418 + of the protocol will not reduce this number. *) 419 + val header_length : int 420 + 421 + (** {2 Management Record Variables} 422 + 423 + These string constants identify the standard management variables that 424 + can be queried using FCGI_GET_VALUES records. They allow the web server 425 + to discover application capabilities. 426 + 427 + The initial set provides information to help the server perform application 428 + and connection management. *) 429 + 430 + (** Variable name "FCGI_MAX_CONNS". The maximum number 431 + of concurrent transport connections this application 432 + will accept, e.g. "1" or "10". *) 433 + val fcgi_max_conns : string 434 + 435 + (** Variable name "FCGI_MAX_REQS". The maximum number 436 + of concurrent requests this application will accept, 437 + e.g. "1" or "50". *) 438 + val fcgi_max_reqs : string 439 + 440 + (** Variable name "FCGI_MPXS_CONNS". "0" if this 441 + application does not multiplex connections (i.e. 442 + handle concurrent requests over each connection), 443 + "1" otherwise. *) 444 + val fcgi_mpxs_conns : string