Description
Provides an origin-bound synchronous HTTP client with bounded connection pooling. Lightweight callers suspend on Flyology I/O; native callers block only their pthread. HTTP/1.1 is the initial protocol engine, while the request/response API does not expose connection ownership.
Add_Header
procedure Add_Header
(Item : in out Request; Name : String; Value : String)
Append one end-to-end request field. Framing, connection, upgrade, and Expect fields are client-controlled and rejected here.
Parameters
- Item
Request to change
- Name
Field name
- Value
Field value
Raised exceptions
- Constraint_Error
Name, Value, or a client-controlled field is invalid
- Flyology
.HTTP.Headers.Headers_Too_Large Request field storage is exhausted
Add_Trailer
procedure Add_Trailer
(Item : in out Request; Name : String; Value : String)
Append one request trailer field. The client generates the Trailer declaration and sends retained trailer values after an unknown-length chunked source finishes. Trailers are rejected for retained or known-length bodies. Known fields affecting framing, routing, authentication, request semantics, or payload interpretation are prohibited, and repeated names are rejected. The caller must know that the field definition permits use in trailers.
Parameters
- Item
Request to change
- Name
Trailer field name
- Value
Trailer field value retained by Item
Raised exceptions
- Constraint_Error
Name is prohibited or repeated in request trailers, or Name or Value has invalid HTTP field syntax
- Flyology
.HTTP.Headers.Headers_Too_Large Trailer storage is exhausted
Body_Complete
function Body_Complete (Item : Response) return Boolean
Report whether body framing is complete and no connection lease remains.
Parameters
- Item
Response to inspect
Return value
True after complete body consumption
Raised exceptions
- Program_Error
Item is not initialized by Execute
Body_Length
type Body_Length is private;
Known or unknown streaming request body length. Unknown bodies use the active protocol's streaming framing; HTTP/1.1 uses chunked coding.
Body_Size
subtype Body_Size is Long_Long_Integer range 0 .. Long_Long_Integer'Last;
Maximum representable request body byte count.
Client
type Client (Capacity : Positive := 4) is limited private;
Origin-bound client. Capacity is the maximum number of open plus connecting transports. Configure must complete before concurrent use. Finalize requests shutdown and closes transports. Execute's aliased controlling parameter lets Ada accessibility reject a response that would escape Item's lifetime. Internal retention also protects cleanup during abort and finalization races.
Record fields
- Capacity
Maximum open plus connecting transport count
Client_Closed
Client_Closed : exception;
Raised after client shutdown rejects a request or interrupts pool admission.
Client_Diagnostics
type Client_Diagnostics is record
Transport_Capacity : Positive;
Pending_Transports : Natural;
Active_Exchanges : Natural;
Reusable_Transports : Natural;
Closing_Transports : Natural;
Admission_Waiters : Natural;
Transports_Created : Natural;
Transport_Reuses : Natural;
Transports_Closed : Natural;
Stale_Retries : Natural;
Admission_Timeouts : Natural;
end record;
Coherent client counters. Exchange and transport counts are separate so a later multiplexed protocol can report several exchanges on one transport without changing this record's meaning.
Record fields
- Transport_Capacity
Configured transport slot bound
- Pending_Transports
Transports being established
- Active_Exchanges
Requests that own protocol exchanges
- Reusable_Transports
Established transports eligible for reuse
- Closing_Transports
Transports being closed outside the pool lock
- Admission_Waiters
Requests waiting for exchange capacity
- Transports_Created
Successfully established transports
- Transport_Reuses
Exchanges assigned an existing transport
- Transports_Closed
Transports removed from the client
- Stale_Retries
Idempotent exchanges retried once after an existing transport failed before producing response bytes
- Admission_Timeouts
Pool waits whose request deadline expired
Configure
procedure Configure
(Item : in out Client;
Origin_Value : Origin;
Pool : Pool_Configuration := Default_Pool_Configuration)
Bind a new client to one origin and immutable pool policy. The call does no DNS, socket, TLS, task, or event-loop work. Reconfiguration and an HTTPS origin without a retained TLS backend is rejected.
Parameters
- Item
Unconfigured client
- Origin_Value
Normalized origin
- Pool
Pool retention policy
Raised exceptions
- Program_Error
Item is configured or arguments are invalid
Configure
procedure Configure
(Item : in out Client;
Origin_Value : Origin;
Backend : not null access Flyology.IO.TLS.Provider'Class;
Pool : Pool_Configuration := Default_Pool_Configuration)
Bind a new client to one origin using an explicit TLS provider. The client retains independently owned provider state, so Backend may be finalized after Configure returns. This overload is required for HTTPS and accepted for HTTP so callers may share configuration code.
Parameters
- Item
Unconfigured client
- Origin_Value
Normalized origin
- Backend
Initialized TLS provider retained by Item
- Pool
Pool retention policy
Raised exceptions
- Program_Error
Item is configured or arguments are invalid
- Flyology
.IO.TLS.TLS_Error Backend cannot be retained
Connection_Error
Connection_Error : exception;
Raised when the origin cannot be resolved or every resolved address fails before an HTTP exchange starts.
Declared_Length
function Declared_Length
(Item : Request_Body_Source) return Body_Length
Return the source's stable framing length. Known lengths generate Content-Length; Unknown_Length selects the protocol's streaming framing.
Parameters
- Item
Source to inspect before its first read
Return value
Known byte count or Unknown_Length
Default_Pool_Configuration
Default_Pool_Configuration : constant Pool_Configuration := (others => <>);
Default conservative pool policy.
Default_Same_Origin_Redirects
Default_Same_Origin_Redirects : constant Redirect_Configuration :=
(Mode => Follow_Same_Origin, Maximum_Hops => 5);
Opt-in policy that follows at most five same-origin redirects.
Diagnostics
function Diagnostics (Item : Client) return Client_Diagnostics
Return coherent exchange and transport diagnostics without starting I/O.
Parameters
- Item
Client to inspect
Return value
Current and cumulative counters
Execute
function Execute
(Item : aliased in out Client;
Value : Request;
Source : in out Request_Body_Source'Class;
Timeout : Duration := 30.0;
Token : access Flyology.Cancellation.Token := null) return Response
Execute one request while pulling its body from Source. The source's Declared_Length controls protocol framing. Source is not retained and is replayed only when it implements Rewindable_Request_Body_Source and the ordinary idempotent stale-transport retry conditions hold. Its exceptions propagate after the leased transport is discarded.
Parameters
- Item
Shared configured client that outlives the result
- Value
Request metadata; a retained body is rejected
- Source
Request body producer used only during this call
- Timeout
Whole-exchange deadline interval
- Token
Optional cancellation source
Return value
Response head with a streaming response body lease
Raised exceptions
- Client_Closed
Client is stopping
- Connection_Error
Resolution or all address attempts fail
- Constraint_Error
Request metadata is unsupported or already contains a retained body
- Request_Body_Error
Source violates its progress contract or ends before a known length is complete
- Protocol_Error
Response framing is malformed or unsupported
- Response_Too_Large
Response head exceeds its bound
- Redirect_Error
An enabled redirect cannot be followed safely
- Flyology
.IO.Timeout_Error Whole-exchange deadline expires
.IO.Device_Error Established transport I/O fails
.IO.Sockets.Socket_Error Socket transmission fails
.IO.TLS.TLS_Error TLS setup or transmission fails
.Cancellation.Operation_Cancelled Token is requested
Execute
function Execute
(Item : aliased in out Client;
Value : Request;
Timeout : Duration := 30.0;
Token : access Flyology.Cancellation.Token := null) return Response
Execute one request. One monotonic Timeout starts before pool admission and covers admission, DNS, all address attempts, TLS, request send, the response head, and later body reads. Negative is unlimited and zero is immediate. Token is borrowed only until the final response head is returned; body reads receive their own optional cancellation token.
Parameters
- Item
Shared configured client that outlives the result
- Value
Request to execute
- Timeout
Whole-exchange deadline interval
- Token
Optional cancellation source An idempotent request assigned a reused transport is retried once when that transport fails before any response byte is received. Retained bodies can be replayed directly; streamed bodies are eligible only when Source implements Rewindable_Request_Body_Source. The retry remains inside the original deadline. Non-idempotent requests are never retried.
Return value
Response head with a streaming body lease
Raised exceptions
- Client_Closed
Client is stopping
- Connection_Error
Resolution or all address attempts fail
- Constraint_Error
Request fields, target, or method-body combination is unsupported; CONNECT is not implemented
- Protocol_Error
Response framing is malformed or unsupported
- Response_Too_Large
Response head exceeds its bound
- Redirect_Error
An enabled redirect cannot be followed safely
- Flyology
.IO.Timeout_Error Whole-exchange deadline expires
.IO.Device_Error Established transport I/O fails
.IO.Sockets.Socket_Error Socket transmission fails
.IO.TLS.TLS_Error TLS setup or transmission fails
.Cancellation.Operation_Cancelled Token is requested
Header
function Header
(Item : Response; Name : String; Occurrence : Positive := 1)
return String
Return one physical response field occurrence.
Parameters
- Item
Response to inspect
- Name
Field name
- Occurrence
One-based occurrence
Return value
Field value or empty when absent
Raised exceptions
- Program_Error
Item is not initialized by Execute
Header_Count
function Header_Count (Item : Response) return Natural
Return the number of physical response fields.
Parameters
- Item
Response to inspect
Return value
Field count
Raised exceptions
- Program_Error
Item is not initialized by Execute
Header_Count
function Header_Count (Item : Response; Name : String) return Natural
Count physical response fields with a case-insensitive name.
Parameters
- Item
Response to inspect
- Name
Field name
Return value
Physical occurrence count
Raised exceptions
- Program_Error
Item is not initialized by Execute
Header_Name
function Header_Name (Item : Response; Index : Positive) return String
Return one response field name by wire order.
Parameters
- Item
Response to inspect
- Index
One-based physical field index
Return value
Preserved field name
Raised exceptions
- Program_Error
Item is not initialized by Execute
- Constraint_Error
Index exceeds Header_Count
Header_Value
function Header_Value (Item : Response; Index : Positive) return String
Return one response field value by wire order.
Parameters
- Item
Response to inspect
- Index
One-based physical field index
Return value
Preserved field value
Raised exceptions
- Program_Error
Item is not initialized by Execute
- Constraint_Error
Index exceeds Header_Count
Known_Length
function Known_Length (Bytes : Body_Size) return Body_Length
Construct a known streaming request body length.
Parameters
- Bytes
Exact number of source bytes to transmit
Return value
Known body length
Negotiated_Protocol
function Negotiated_Protocol (Item : Response) return Protocol
Return the negotiated protocol.
Parameters
- Item
Response to inspect
Return value
HTTP_1_1_Protocol in the initial implementation
Raised exceptions
- Program_Error
Item is not initialized by Execute
No_Redirects
No_Redirects : constant Redirect_Configuration := (others => <>);
Default policy: return redirect responses without following them.
Pool_Configuration
type Pool_Configuration is record
Max_Idle : Natural := 1;
Idle_Timeout : Duration := 30.0;
Max_Connection_Age : Duration := 300.0;
Max_Requests_Per_Connection : Natural := 0;
end record;
Pool reuse and retention policy. Capacity remains the Client discriminant and bounds open plus connecting slots.
Record fields
- Max_Idle
Maximum reusable connections retained, capped by client capacity; zero disables reuse without disabling concurrent requests
- Idle_Timeout
Seconds an unused connection may remain reusable; negative disables the age check
- Max_Connection_Age
Total reusable lifetime in seconds; negative disables the age check
- Max_Requests_Per_Connection
Total requests before rotation; zero disables request-count rotation
Prune_Idle
procedure Prune_Idle (Item : in out Client)
Close every currently idle connection. Active leases are unaffected.
Parameters
- Item
Configured client
Read
procedure Read
(Item : in out Request_Body_Source;
Data : out Ada.Streams.Stream_Element_Array;
Last : out Ada.Streams.Stream_Element_Offset;
Finished : out Boolean;
Timeout : Duration;
Token : access Flyology.Cancellation.Token)
Produce the next request body bytes.
Parameters
- Item
Source state to advance
- Data
Client-owned destination buffer
- Last
Last produced byte, or Data'First - 1
- Finished
Whether the source has no bytes after this call
- Timeout
Remaining whole-exchange deadline interval
- Token
Optional cancellation source from Execute
Read_All
function Read_All
(Item : in out Response;
Maximum : Natural := 1_024 * 1_024;
Token : access Flyology.Cancellation.Token := null)
return Flyology.Bytes.Unbounded_Bytes
Read the complete remaining body into owned storage under the original deadline. Maximum bounds decoded bytes retained by this convenience operation.
Parameters
- Item
Active response
- Maximum
Maximum decoded bytes
- Token
Optional cancellation source borrowed for this call
Return value
Complete retained body
Raised exceptions
- Program_Error
Item is not initialized by Execute
- Response_Too_Large
Maximum would be exceeded
- Client_Closed
Client shutdown interrupts the exchange
- Protocol_Error
Response body framing is malformed
- Flyology
.IO.Timeout_Error Whole-exchange deadline expires
.IO.Device_Error Established transport I/O fails
.IO.Sockets.Socket_Error Socket reception fails
.IO.TLS.TLS_Error TLS reception fails
.Cancellation.Operation_Cancelled Token is requested
Read_Body
procedure Read_Body
(Item : in out Response;
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 response representation bytes. Fixed-length and chunked framing are removed. Last is Data'First - 1 when no bytes are produced. Finished becomes true only after complete framing; that transition releases or closes the underlying connection. The Execute deadline and token remain authoritative and are never restarted.
Parameters
- Item
Active response
- Data
Caller-owned destination
- Last
Last decoded byte, or Data'First - 1
- Finished
Whether response framing is complete
- Token
Optional cancellation source borrowed for this call
Raised exceptions
- Program_Error
Item is not initialized by Execute
- Client_Closed
Client shutdown interrupts the exchange
- Protocol_Error
Response body framing is malformed
- Flyology
.IO.Timeout_Error Whole-exchange deadline expires
.IO.Device_Error Established transport I/O fails
.IO.Sockets.Socket_Error Socket reception fails
.IO.TLS.TLS_Error TLS reception fails
.Cancellation.Operation_Cancelled Token is requested
Reason_Phrase
function Reason_Phrase (Item : Response) return String
Return the final response reason phrase. HTTP/2 and later protocols may return an empty string because they do not carry one.
Parameters
- Item
Response to inspect
Return value
Preserved HTTP/1.x reason phrase after its status separator
Raised exceptions
- Program_Error
Item is not initialized by Execute
Redirect_Configuration
type Redirect_Configuration is record
Mode : Redirect_Mode := Return_Redirects;
Maximum_Hops : Redirect_Limit := 5;
end record;
Per-request redirect policy.
Record fields
- Mode
Whether redirects are returned or followed within the origin
- Maximum_Hops
Maximum redirects followed before Redirect_Error
Redirect_Error
Redirect_Error : exception;
Raised when an enabled redirect cannot be followed safely because its target is invalid, repeats a prior target, exceeds the configured hop limit, or requires replaying a one-shot request source.
Redirect_Limit
subtype Redirect_Limit is Natural range 0 .. 20;
Supported bound for automatically followed redirect hops.
Redirect_Mode
type Redirect_Mode is (Return_Redirects, Follow_Same_Origin);
Automatic redirect behavior. Returning redirects is the default and preserves the response exactly as received. Same-origin following never sends a request to a different scheme, host, or port.
Enumeration literals
- Return_Redirects
Return every redirect response to the caller
- Follow_Same_Origin
Follow eligible redirects within the client origin
Request
type Request is private;
Mutable request value. Bodies are retained as owned bytes so request transmission remains valid across task suspension.
Request_Body_Error
Request_Body_Error : exception;
Raised when a streaming request body violates the progress contract or does not finish on exactly its positive declared length.
Request_Body_Source
type Request_Body_Source is limited interface;
Pull source for a streaming request body. Execute queries Declared_Length once, calls Read serially, and never retains the source after returning. The declared length must remain stable during Execute. Implementations must honor the remaining whole-exchange timeout and cancellation token when they perform blocking work. A call must either produce at least one byte or set Finished. Last is Data'First - 1 when no bytes are produced.
Response
type Response is limited private;
Limited response owning one exchange lease until its body is consumed. Reading the complete body returns a reusable connection to the pool. Finalizing an incomplete response closes it without draining.
Response_Too_Large
Response_Too_Large : exception;
Raised when retained response metadata or a Read_All body exceeds its bound.
Rewind
procedure Rewind
(Item : in out Rewindable_Request_Body_Source)
Restore a rewindable source to its initial byte before one safe retry.
Parameters
- Item
Source whose exact initial sequence is restored
Rewindable_Request_Body_Source
type Rewindable_Request_Body_Source is
limited interface and Request_Body_Source;
Request source that can reproduce exactly the same byte sequence after a failed transport attempt. Rewind must be nonblocking and restore the initial cursor without changing Declared_Length. Execute calls it only after discarding a failed reused transport and only when the method is idempotent and no response byte was received.
Set_Body
procedure Set_Body
(Item : in out Request; Value : Ada.Streams.Stream_Element_Array)
Replace the request body from contiguous bytes.
Parameters
- Item
Request to change
- Value
Request representation bytes
Set_Body
procedure Set_Body (Item : in out Request; Value : String)
Replace the request body using a one-to-one byte mapping.
Parameters
- Item
Request to change
- Value
Request representation bytes
Set_Expect_Continue
procedure Set_Expect_Continue
(Item : in out Request;
Enabled : Boolean := True;
Wait_Timeout : Duration := 1.0)
Enable or disable the Expect: 100-continue handshake. When enabled for a nonempty retained or streaming body, Execute sends the request head first and waits up to Wait_Timeout for 100 Continue or a final response. A positive wait expiry with no partial response sends the body; a negative value waits within the whole exchange deadline and zero sends immediately after the head. A final response suppresses body reads and transmission. A 417 final response received before body transmission is retried once on a fresh transport without the expectation, within the same deadline and shared automatic-retry budget. The whole exchange deadline is never extended.
Parameters
- Item
Request to change
- Enabled
Whether to generate Expect: 100-continue
- Wait_Timeout
Maximum continue-specific wait in seconds
Set_Method
procedure Set_Method (Item : in out Request; Value : Method)
Replace the request method.
Parameters
- Item
Request to change
- Value
Validated method
Set_Redirects
procedure Set_Redirects
(Item : in out Request; Value : Redirect_Configuration)
Replace the request's automatic redirect policy. One monotonic Execute deadline covers every hop and every intermediate response-body drain. Cross-origin redirects are always returned to the caller.
Parameters
- Item
Request to change
- Value
Redirect mode and hop bound
Set_Target
procedure Set_Target (Item : in out Request; Value : String)
Replace the origin-form request target. Asterisk-form is retained for OPTIONS and validated when Execute observes the complete Request. Absolute-form, authority-form, fragments, non-ASCII bytes, spaces, control characters, and targets over 8 KiB are rejected.
Parameters
- Item
Request to change
- Value
Origin-form target
Raised exceptions
- Constraint_Error
Value is not a supported request target
Shutdown
procedure Shutdown (Item : in out Client; Timeout : Duration := 5.0)
Terminally reject admission, cancel admitted transport operations, close idle connections, and wait up to Timeout for leases and connecting slots to drain. A timeout leaves Item stopping and may be retried.
Parameters
- Item
Client to stop
- Timeout
Drain deadline interval; negative waits indefinitely
Raised exceptions
- Flyology
.IO.Timeout_Error Active leases do not drain
Status
function Status (Item : Response) return Status_Code
Return the final response status.
Parameters
- Item
Response to inspect
Return value
Three-digit status
Raised exceptions
- Program_Error
Item is not initialized by Execute
Trailer
function Trailer
(Item : Response; Name : String; Occurrence : Positive := 1)
return String
Return one completed chunked trailer occurrence.
Parameters
- Item
Response whose body has completed
- Name
Trailer name
- Occurrence
One-based occurrence
Return value
Trailer value or empty when absent
Raised exceptions
- Program_Error
Item is uninitialized or its body is incomplete
Trailer_Count
function Trailer_Count (Item : Response) return Natural
Return the number of physical trailer fields available after body completion.
Parameters
- Item
Response to inspect
Return value
Trailer field count
Raised exceptions
- Program_Error
Item is uninitialized or its body is incomplete
Trailer_Count
function Trailer_Count (Item : Response; Name : String) return Natural
Count completed chunked trailer fields with a case-insensitive name.
Parameters
- Item
Response whose body has completed
- Name
Trailer name
Return value
Physical occurrence count
Raised exceptions
- Program_Error
Item is uninitialized or its body is incomplete
Trailer_Name
function Trailer_Name (Item : Response; Index : Positive) return String
Return one trailer field name by wire order.
Parameters
- Item
Response to inspect
- Index
One-based physical field index
Return value
Preserved trailer name
Raised exceptions
- Program_Error
Item is uninitialized or its body is incomplete
- Constraint_Error
Index exceeds Trailer_Count
Trailer_Value
function Trailer_Value (Item : Response; Index : Positive) return String
Return one trailer field value by wire order.
Parameters
- Item
Response to inspect
- Index
One-based physical field index
Return value
Preserved trailer value
Raised exceptions
- Program_Error
Item is uninitialized or its body is incomplete
- Constraint_Error
Index exceeds Trailer_Count
Unknown_Length
Unknown_Length : constant Body_Length;
Unknown streaming request body length.