← All compilation units

Flyology.HTTP.Server

Description

Provides a bounded HTTP/1.1 connection engine over a task-aware transport. The engine supports persistent requests, fixed-length and chunked request bodies, fixed responses, server-sent events, and RFC 6455 WebSockets.

Accept_Body

procedure Accept_Body
  (Item  : in out Connection;
   Token : access Flyology.Cancellation.Token := null)

Accept the current request body, sending 100 Continue when requested. The original Read_Request_Head deadline remains authoritative.

Parameters
Item

HTTP connection with an unread request body

Token

Optional cancellation source

Accept_WebSocket

procedure Accept_WebSocket
  (Item     : in out Connection;
   Value    : Request;
   Protocol : String := "";
   Origin_Policy : WebSocket_Origin_Policy := Reject_Browser_Origins;
   Allowed_Origin : String := "";
   Timeout  : Duration := 30.0;
   Token    : access Flyology.Cancellation.Token := null;
   Compression : WebSocket_Compression_Mode := No_WebSocket_Compression)

Perform an RFC 6455 server upgrade for Request. The client key and required Upgrade, Connection, and version fields are validated.

Parameters
Item

HTTP connection

Value

Request being upgraded

Protocol

Optional selected subprotocol token

Origin_Policy

Browser-origin policy; secure non-browser default

Allowed_Origin

Exact origin required by Require_Exact_Origin

Timeout

Transport send deadline

Token

Optional cancellation source

Compression

Explicit RFC 7692 negotiation policy

Raised exceptions
Protocol_Error

Request is not a valid version 13 upgrade

Begin_Response_Stream

procedure Begin_Response_Stream
  (Item          : in out Connection;
   Status        : Positive;
   Content_Type  : String;
   Extra_Headers : String := "";
   Close         : Boolean := False;
   Timeout       : Duration := 30.0;
   Token         : access Flyology.Cancellation.Token := null)

Start an arbitrary streaming response. HTTP/1.1 uses chunked framing; HTTP/1.0 uses connection-close delimiting. The handler remains the sole writer until End_Response_Stream completes.

Parameters
Item

HTTP connection

Status

HTTP status

Content_Type

Media type, or empty to omit

Extra_Headers

Additional validated response fields

Close

Force connection closure after the stream

Timeout

Transport send deadline

Token

Optional cancellation source

Begin_SSE

procedure Begin_SSE
  (Item          : in out Connection;
   Extra_Headers : String := "";
   Timeout       : Duration := 30.0;
   Token         : access Flyology.Cancellation.Token := null)

Start a chunked text/event-stream response.

Parameters
Item

HTTP connection

Extra_Headers

Additional validated response fields

Timeout

Transport send deadline

Token

Optional cancellation source

Body_Complete

function Body_Complete (Item : Connection) return Boolean

Report whether the current request body and trailers are consumed.

Parameters
Item

HTTP connection

Return value

True when another request may be parsed after the response

Buffer_Request_Body

procedure Buffer_Request_Body
  (Item  : in out Connection;
   Value : in out Request;
   Token : access Flyology.Cancellation.Token := null)

Buffer the current decoded body into Value under the configured shared ingress budget. This is the routed equivalent of Read_Request's body phase and preserves the request-head deadline.

Parameters
Item

HTTP connection with an unread body

Value

Request head previously read from Item

Token

Optional cancellation source

Raised exceptions
Resource_Exhausted

Shared buffered ingress budget is full

Close_WebSocket

procedure Close_WebSocket
  (Item    : in out Connection;
   Code    : Positive := 1_000;
   Reason  : String := "";
   Timeout : Duration := 30.0;
   Token   : access Flyology.Cancellation.Token := null)

Send a normal WebSocket close frame and make Item terminal.

Parameters
Item

Upgraded WebSocket connection

Code

RFC 6455 close status

Reason

Optional UTF-8 close reason

Timeout

Transport send deadline

Token

Optional cancellation source

Configure_Ingress_Budget

procedure Configure_Ingress_Budget
  (Item   : in out Connection;
   Budget : not null access Ingress_Budget)

Attach one shared ingress budget before the first request is read. The budget must outlive Item and cannot be replaced while bytes are reserved.

Parameters
Item

HTTP connection to configure

Budget

Shared server budget

Connection

type Connection (Channel : not null access Transport'Class) is limited
  private;

HTTP/WebSocket state for one transport. The object and transport must remain owned by one handler at a time. Buffered pipelined input is kept between Read_Request calls.

Record fields
Channel

Borrowed transport kept alive for this object

Content

function Content (Item : Request) return String

Return the decoded fixed-length or chunked request body.

Parameters
Item

Request to inspect

Return value

Body bytes represented as an Ada String

Current

function Current (Item : Ingress_Budget) return Ingress_Budget_Snapshot

Read current budget counters.

Parameters
Item

Shared server budget

Return value

Stable accounting snapshot

Current

function Current (Item : Outbound_Budget) return Outbound_Budget_Snapshot

Read current outbound budget counters.

Parameters
Item

Shared application/server budget

Return value

Stable accounting snapshot

Default_Ingress_Budget_Bytes

Default_Ingress_Budget_Bytes : constant := 64 * 1_024 * 1_024;

Process-wide retained-payload budget used by connections that do not attach a server-specific Ingress_Budget.

Default_Max_WebSocket_Message

Default_Max_WebSocket_Message : constant := 1_024 * 1_024;

Default maximum retained or reassembled inbound WebSocket message.

Default_Outbound_Budget_Bytes

Default_Outbound_Budget_Bytes : constant := 64 * 1_024 * 1_024;

Process-wide retained outbound-message budget used by high-level SSE and WebSocket sessions without an application-supplied budget.

Discard_Body

procedure Discard_Body
  (Item  : in out Connection;
   Token : access Flyology.Cancellation.Token := null)

Consume and discard the current body under the original absolute deadline. This is explicit because silently draining an unwanted body can itself be a slow-client attack.

Parameters
Item

HTTP connection with a current request

Token

Optional cancellation source

End_Response_Stream

procedure End_Response_Stream
  (Item    : in out Connection;
   Timeout : Duration := 30.0;
   Token   : access Flyology.Cancellation.Token := null)

Complete a streaming response and release the connection for another request when persistence remains safe.

Parameters
Item

Active streaming response

Timeout

Transport send deadline

Token

Optional cancellation source

End_SSE

procedure End_SSE
  (Item    : in out Connection;
   Timeout : Duration := 30.0;
   Token   : access Flyology.Cancellation.Token := null)

Finish a chunked SSE response. The HTTP connection can process another request when persistence remains enabled.

Parameters
Item

Active SSE response

Timeout

Transport send deadline

Token

Optional cancellation source

Expectation_Failed

Expectation_Failed : exception;

Raised for an unsupported or malformed Expect request field.

Header

function Header (Item : Request; Name : String) return String

Return a case-insensitive header value with surrounding whitespace removed. Repeated fields are comma-joined in wire order.

Parameters
Item

Request to inspect

Name

Header field name

Return value

Header value, or an empty string when absent

Header_Count

function Header_Count (Item : Request; Name : String) return Natural

Count physical occurrences of one case-insensitive request field.

Parameters
Item

Request to inspect

Name

Header field name

Return value

Physical field count before comma joining

Header_Has_Token

function Header_Has_Token
  (Item : Request; Name : String; Value : String) return Boolean

Report whether a comma-separated header contains a token.

Parameters
Item

Request to inspect

Name

Header field name

Value

Token sought case-insensitively

Return value

True when the token occurs as a complete list member

Ingress_Budget

type Ingress_Budget (Limit : Positive) is limited private;

Nonblocking shared budget for retained request bodies and WebSocket messages. Streaming operations write into caller-owned buffers and do not reserve their payload bytes here.

Record fields
Limit

Maximum simultaneously reserved payload bytes

Ingress_Budget_Snapshot

type Ingress_Budget_Snapshot is record
   Limit   : Positive;
   Current : Natural;
   Peak    : Natural;
   Denials : Natural;
end record;

Snapshot of shared buffered-ingress accounting.

Record fields
Limit

Configured maximum reserved bytes

Current

Bytes currently reserved

Peak

Highest observed reservation

Denials

Failed nonblocking reservation attempts

Max_Header_Bytes

Max_Header_Bytes : constant := 16 * 1_024;

Maximum bytes before the terminating empty request-header line.

Max_Request_Body

Max_Request_Body : constant := 1_024 * 1_024;

Maximum decoded request representation.

Max_WebSocket_Frame

Max_WebSocket_Frame : constant := 16 * 1_024 * 1_024;

Maximum supported inbound or generated WebSocket frame payload. Callers may opt into this bound with Receive_WebSocket's Max_Message parameter.

Method

function Method (Item : Request) return String

Return the request method exactly as received.

Parameters
Item

Request to inspect

Return value

Case-sensitive method token

Narrow_Body_Limit

procedure Narrow_Body_Limit
  (Item    : in out Connection;
   Maximum : Natural)

Reduce the decoded body limit after request-head routing. This must be called before body consumption and can never increase the parser limit.

Parameters
Item

HTTP connection with an unread request body

Maximum

New decoded-body maximum

Narrow_Request_Deadline

procedure Narrow_Request_Deadline
  (Item     : in out Connection;
   Deadline : Ada.Real_Time.Time)

Shorten the current request deadline. A later value is rejected so no application layer can restart or extend slow-client protection.

Parameters
Item

HTTP connection with a current request

Deadline

Earlier absolute monotonic deadline

Outbound_Budget

type Outbound_Budget (Limit : Positive) is limited private;

Nonblocking shared budget for application messages retained by the optional SSE and WebSocket lifecycle APIs.

Record fields
Limit

Maximum simultaneously retained outbound bytes

Outbound_Budget_Snapshot

subtype Outbound_Budget_Snapshot is Ingress_Budget_Snapshot;

Snapshot of shared queued-outbound accounting.

Payload_Too_Large

Payload_Too_Large : exception;

Raised when the declared or decoded body exceeds the active limit.

Read_Body

procedure Read_Body
  (Item     : in out Connection;
   Data     : out Ada.Streams.Stream_Element_Array;
   Last     : out Ada.Streams.Stream_Element_Offset;
   Finished : out Boolean;
   Token    : access Flyology.Cancellation.Token := null)

Stream decoded body bytes into caller-owned storage. Fixed-length and chunked framing are removed. Finished becomes true only after all body framing and trailers are consumed. The request-head deadline is never restarted by incremental reads.

Parameters
Item

HTTP connection with a current request

Data

Caller-owned destination

Last

Last decoded byte, or Data'First - 1 when none

Finished

True after the complete body and trailers

Token

Optional cancellation source

Read_Request

procedure Read_Request
  (Item        : in out Connection;
   Value       : out Request;
   Peer_Closed : out Boolean;
   Timeout     : Duration := 30.0;
   Max_Body    : Natural := Max_Request_Body;
   Token       : access Flyology.Cancellation.Token := null)

Read and parse the next request, buffering its complete decoded body. This compatibility operation is implemented over Read_Request_Head and Read_Body. When Item has an ingress budget, fixed bodies reserve their declared length and chunked bodies reserve Max_Body before allocation. Resource_Exhausted is raised without waiting when reservation fails. Header and body limits are enforced before allocation grows beyond their public bounds. One monotonic Timeout covers the complete header and decoded body, so incremental progress cannot extend a slow client's deadline. HTTP/1.1 requires Host.

Parameters
Item

HTTP connection

Value

Parsed request on success

Peer_Closed

True only when the peer closes between requests

Timeout

Deadline used by each transport receive

Max_Body

Application body limit, capped by Max_Request_Body

Token

Optional cancellation source

Raised exceptions
Protocol_Error

Input is malformed, oversized, or unsupported

Resource_Exhausted

Shared buffered ingress budget is full

Read_Request_Head

procedure Read_Request_Head
  (Item            : in out Connection;
   Value           : out Request;
   Peer_Closed     : out Boolean;
   Header_Timeout  : Duration;
   Request_Timeout : Duration;
   Max_Body        : Natural := Max_Request_Body;
   Token           : access Flyology.Cancellation.Token := null)

Read and validate a request head with distinct absolute budgets for the header and complete request. Both clocks start before the first header byte, so neither incremental headers nor a streamed body can restart a deadline. Request_Timeout may exceed Header_Timeout for explicitly admitted long-lived responses such as SSE and WebSocket lifecycles.

Parameters
Item

HTTP connection

Value

Parsed request head on success; Content is empty

Peer_Closed

True only when the peer closes between requests

Header_Timeout

Absolute request-head deadline interval

Request_Timeout

Absolute complete-request deadline interval

Max_Body

Application body limit, capped by Max_Request_Body

Token

Optional cancellation source

Read_Request_Head

procedure Read_Request_Head
  (Item        : in out Connection;
   Value       : out Request;
   Peer_Closed : out Boolean;
   Timeout     : Duration := 30.0;
   Max_Body    : Natural := Max_Request_Body;
   Token       : access Flyology.Cancellation.Token := null)

Read and validate the next request head without buffering its body. Body framing remains attached to Item and must be consumed with Read_Body or Discard_Body before another request can be read. One monotonic Timeout begins here and covers the complete streamed body. Expect: 100-continue is not emitted until Accept_Body is called.

Parameters
Item

HTTP connection

Value

Parsed request head on success; Content is empty

Peer_Closed

True only when the peer closes between requests

Timeout

Absolute header-and-body deadline interval

Max_Body

Application body limit, capped by Max_Request_Body

Token

Optional cancellation source

Receive

procedure Receive
  (Item    : in out Transport;
   Data    : out Ada.Streams.Stream_Element_Array;
   Last    : out Ada.Streams.Stream_Element_Offset;
   Timeout : Duration;
   Token   : access Flyology.Cancellation.Token)

Receive one available transport chunk.

Parameters
Item

Transport to read

Data

Destination buffer

Last

Last byte received, or Data'First - 1 on orderly closure

Timeout

Operation deadline interval in seconds

Token

Optional cancellation source that must outlive the call

Receive_WebSocket

procedure Receive_WebSocket
  (Item    : in out Connection;
   Kind    : out WebSocket_Data_Kind;
   Data    : out Flyology.Bytes.Unbounded_Bytes;
   Closed  : out Boolean;
   Max_Message : Natural := Default_Max_WebSocket_Message;
   Timeout : Duration := 30.0;
   Message_Timeout : Duration := 30.0;
   Token   : access Flyology.Cancellation.Token := null)

Receive one complete client message, reassembling fragments within Max_Message. Timeout bounds one wait quantum; Message_Timeout is one monotonic deadline retained across retry quanta, all fragments, and interleaved control frames. Ping is answered automatically and close sets Closed. Client frames must be masked. Protocol failure makes Item terminal. Negotiated compression is decoded before return; compressed and decompressed storage is charged to the shared ingress budget. A Timeout expiry may be retried while Item remains active. Expiry of the retained whole-message deadline or a control-frame write makes Item terminal before raising Timeout_Error.

Parameters
Item

Upgraded WebSocket connection

Kind

Text or binary message kind

Data

Message payload

Closed

True after a valid close frame

Max_Message

Application message limit, capped by the 16 MiB supported frame maximum; the default remains 1 MiB

Timeout

Transport receive/send wait quantum

Message_Timeout

Whole-message monotonic deadline

Token

Optional cancellation source

Raised exceptions
Resource_Exhausted

Shared message reassembly budget is full

Release

procedure Release (Item : in out Ingress_Budget; Bytes : Natural)

Release a prior successful reservation.

Parameters
Item

Shared server budget

Bytes

Reserved bytes to return

Release

procedure Release (Item : in out Outbound_Budget; Bytes : Natural)

Release a prior outbound reservation.

Parameters
Item

Shared application/server budget

Bytes

Reserved bytes to return

Request

type Request is private;

One parsed request. Values are replaced by Read_Request.

Request_Deadline

function Request_Deadline (Item : Connection) return Ada.Real_Time.Time

Return the absolute monotonic deadline established for the current request. Time_Last represents an unlimited deadline.

Parameters
Item

HTTP connection

Return value

Original or narrowed request deadline

Resource_Exhausted

Resource_Exhausted : exception;

Raised when a buffered compatibility operation cannot reserve its payload from the configured shared ingress budget.

Respond

procedure Respond
  (Item          : in out Connection;
   Status        : Positive;
   Content_Type  : String;
   Payload       : String;
   Extra_Headers : String := "";
   Close         : Boolean := False;
   Timeout       : Duration := 30.0;
   Token         : access Flyology.Cancellation.Token := null)

Send one complete fixed-length response. Reason is derived from Status. Extra_Headers is a sequence of complete CRLF-terminated fields and must not contain an empty line. HEAD sends the declared body length without body bytes. Statuses 204, 205, and 304 reject nonempty Payload; 204 and 304 omit Content-Length. Connection persistence follows the request unless Close is true.

Parameters
Item

HTTP connection

Status

Three-digit HTTP status

Content_Type

Media type, or empty to omit

Payload

Response representation

Extra_Headers

Additional validated header fields

Close

Force connection closure after the response

Timeout

Transport send deadline

Token

Optional cancellation source

Response_Started

function Response_Started (Item : Connection) return Boolean

Report whether the current request already received a response or protocol upgrade.

Parameters
Item

HTTP connection

Return value

True after Respond, Begin_SSE, or Accept_WebSocket

Send_All

procedure Send_All
  (Item    : in out Transport;
   Data    : Ada.Streams.Stream_Element_Array;
   Timeout : Duration;
   Token   : access Flyology.Cancellation.Token)

Send a complete transport chunk.

Parameters
Item

Transport to write

Data

Source bytes

Timeout

Operation deadline interval in seconds

Token

Optional cancellation source that must outlive the call

Send_Event

procedure Send_Event
  (Item    : in out Connection;
   Data    : String;
   Event   : String := "";
   Id      : String := "";
   Retry   : Natural := 0;
   Timeout : Duration := 30.0;
   Token   : access Flyology.Cancellation.Token := null;
   Include_Id : Boolean := False;
   Include_Retry : Boolean := False)

Send one SSE event as one HTTP chunk. Embedded newlines in Data become repeated data fields. Empty Event and ordinary default Id/Retry values are omitted; include flags allow the valid empty-id reset and retry 0.

Parameters
Item

Active SSE response

Data

Event data

Event

Optional event type

Id

Optional event id

Retry

Optional client retry interval in milliseconds

Timeout

Transport send deadline

Token

Optional cancellation source

Include_Id

Emit id even when Id is empty

Include_Retry

Emit retry even when Retry is zero

Send_SSE_Comment

procedure Send_SSE_Comment
  (Item    : in out Connection;
   Comment : String := "";
   Timeout : Duration := 30.0;
   Token   : access Flyology.Cancellation.Token := null)

Send one SSE comment, commonly used as a heartbeat without dispatching an application message in EventSource clients.

Parameters
Item

Active SSE response

Comment

Comment text; embedded newlines become comment fields

Timeout

Transport send deadline

Token

Optional cancellation source

Send_WebSocket

procedure Send_WebSocket
  (Item    : in out Connection;
   Kind    : WebSocket_Data_Kind;
   Data    : Ada.Streams.Stream_Element_Array;
   Timeout : Duration := 30.0;
   Token   : access Flyology.Cancellation.Token := null)

Send one unmasked, final server data frame.

Parameters
Item

Upgraded WebSocket connection

Kind

Text or binary message kind

Data

Frame payload

Timeout

Transport send deadline

Token

Optional cancellation source

Send_WebSocket

procedure Send_WebSocket
  (Item    : in out Connection;
   Kind    : WebSocket_Data_Kind;
   Data    : Flyology.Bytes.Unbounded_Bytes;
   Timeout : Duration := 30.0;
   Token   : access Flyology.Cancellation.Token := null)

Send one unmasked, final server data frame directly from owned bytes. This overload writes large messages in bounded chunks and does not form a contiguous copy on the caller's task stack.

Parameters
Item

Upgraded WebSocket connection

Kind

Text or binary message kind

Data

Owned frame payload

Timeout

Whole-frame transport send deadline

Token

Optional cancellation source

Send_WebSocket

procedure Send_WebSocket
  (Item    : in out Connection;
   Data    : String;
   Timeout : Duration := 30.0;
   Token   : access Flyology.Cancellation.Token := null)

Send one unmasked, final UTF-8 text frame. Data is interpreted as UTF-8 encoded octets and validated before any frame bytes are written.

Parameters
Item

Upgraded WebSocket connection

Data

UTF-8 byte string

Timeout

Transport send deadline

Token

Optional cancellation source

Should_Close

function Should_Close (Item : Connection) return Boolean

Report whether the last request or response requires transport close.

Parameters
Item

HTTP connection

Return value

True when no further request may be processed

Target

function Target (Item : Request) return String

Return the request target exactly as received.

Parameters
Item

Request to inspect

Return value

Origin-form or application-defined target

Transport

type Transport is limited interface;

Transport boundary shared by plain and TLS connections. Implementations retain closing ownership and must preserve Flyology cancellation and deadline semantics.

Try_Reserve

procedure Try_Reserve
  (Item : in out Ingress_Budget;
   Bytes : Natural;
   Granted : out Boolean)

Attempt to reserve Bytes without suspending a handler.

Parameters
Item

Shared server budget

Bytes

Requested buffered payload bytes

Granted

True only when the reservation was recorded

Try_Reserve

procedure Try_Reserve
  (Item : in out Outbound_Budget;
   Bytes : Natural;
   Granted : out Boolean)

Attempt to reserve outbound bytes without suspending a producer.

Parameters
Item

Shared application/server budget

Bytes

Requested retained bytes

Granted

True only when recorded

Version

function Version (Item : Request) return HTTP_Version

Return the parsed protocol version.

Parameters
Item

Request to inspect

Return value

HTTP/1.0 or HTTP/1.1

WebSocket_Compression_Mode

type WebSocket_Compression_Mode is
  (No_WebSocket_Compression, Permessage_Deflate);

WebSocket extension policy selected explicitly at upgrade time. Permessage_Deflate negotiates RFC 7692 with no context takeover in both directions so compression state and history do not cross message boundaries. Outbound compression uses a 32 KiB history, so an offer requiring server_max_window_bits below 15 is declined. Applications must assess compression side channels before enabling it for secret-bearing messages.

Enumeration literals
No_WebSocket_Compression

Decline compression offers

Permessage_Deflate

Negotiate bounded per-message raw DEFLATE

WebSocket_Data_Kind

type WebSocket_Data_Kind is (Text_Frame, Binary_Frame);

WebSocket application-data kind.

Enumeration literals
Text_Frame

Validated UTF-8 text payload

Binary_Frame

Binary payload

WebSocket_Origin_Policy

type WebSocket_Origin_Policy is
  (Reject_Browser_Origins, Allow_Any_Origin, Require_Exact_Origin);

Browser-origin policy applied before a WebSocket upgrade.

Enumeration literals
Reject_Browser_Origins

Reject requests containing Origin

Allow_Any_Origin

Accept zero or one syntactically bounded Origin

Require_Exact_Origin

Require exact case-sensitive Allowed_Origin

Write_Response_Chunk

procedure Write_Response_Chunk
  (Item    : in out Connection;
   Data    : Ada.Streams.Stream_Element_Array;
   Timeout : Duration := 30.0;
   Token   : access Flyology.Cancellation.Token := null)

Send one binary streaming response chunk with transport backpressure. Empty data is a no-op and HEAD suppresses data bytes.

Parameters
Item

Active streaming response

Data

Response bytes

Timeout

Transport send deadline

Token

Optional cancellation source

Write_Response_Chunk

procedure Write_Response_Chunk
  (Item    : in out Connection;
   Data    : String;
   Timeout : Duration := 30.0;
   Token   : access Flyology.Cancellation.Token := null)

Send one streaming response chunk with transport backpressure. Empty data is a no-op and HEAD suppresses data bytes.

Parameters
Item

Active streaming response

Data

Response bytes

Timeout

Transport send deadline

Token

Optional cancellation source