NAME
Unblock::HTTP1::Server - One non-blocking HTTP/1 server connection
SYNOPSIS
use Unblock::HTTP1::Server;
my $server = Unblock::HTTP1::Server->new(
transport => $transport,
on_request => sub {
my ($tx, $request) = @_;
$tx->respond(
status => 200,
body => "hello\n",
);
},
);
$server->input($bytes);
DESCRIPTION
Unblock::HTTP1::Server owns the HTTP/1 protocol state for one accepted server connection.
It is not a listener and it does not create sockets, perform TLS, or run an event loop. A host framework accepts the connection and feeds its bytes into this object.
Supply transport => $host to new() to deliver outgoing wire bytes automatically through the host. The host owns its socket and implements unblock_send(), unblock_finish(), and unblock_abort(). See Unblock::HTTP1::Integration for a complete example and the contract.
The lower-level form is:
my $server = Unblock::HTTP1::Server->new(
on_request => sub { ... },
);
In that mode the caller feeds input with input() and drains output with output().
The Server supports persistent HTTP/1 connections and safely handles pipelined request bytes. Only one transaction is active at a time; bytes for a later request remain buffered until the prior transaction retires.
RECEIVE BODY OPTIONS
receive_body accepts buffered or stream. Streaming remains the default. max_buffered_body_bytes is a positive byte limit, defaulting to 64 MiB. Zero does not mean unlimited. Buffered reception installs the body on the same Uniform message before freezing it and invoking the body-completion callback. Empty completed bodies have an empty string representation. The engine releases retained chunks on failure or cancellation.
Select streaming per transaction with $tx->on_data(...) during the header callback. Do not combine buffered mode with legacy on_body. Do not combine on_data and on_body. See "RECEIVE AND FINISH CALLBACKS" in Unblock::HTTP1::Transaction.
A buffer limit failure closes the HTTP/1 connection. It does not call successful body completion.
CONSTRUCTOR
new
my $server = Unblock::HTTP1::Server->new(
on_request => sub { ... },
%options,
);
Creates one server protocol engine.
on_request is required.
Other callbacks are optional:
on_body
on_request_end
on_error
on_switch
Common options are:
transport-
Optional framework-owned object implementing
unblock_send($bytes),unblock_finish(), andunblock_abort($reason). The engine holds a weak reference to it. See Unblock::HTTP1::Integration. max_head_size-
Maximum request head size in bytes. Default: 65536.
max_headers-
Maximum number of header or trailer fields. Default: 100.
max_chunk_extension_size-
Maximum total chunk-extension bytes allowed for one chunked message. Default: 16384.
high_water-
High-water mark for the HTTP output queue. Default: 65536.
low_water-
Low-water mark used to resume a blocked streaming response producer. Default: 32768.
REQUEST CALLBACKS
on_request
on_request => sub {
my ($tx, $request) = @_;
}
Required.
Called once after a complete request head has been parsed and validated.
$request is a canonical Uniform::HTTP::Request. Its method, target, version, and headers are available at this point. The request body and trailers may still be arriving.
The application may respond immediately from on_request; it does not need to wait for on_request_end unless its response depends on the complete request body.
For a valid Expect: 100-continue request with a body, the engine emits 100 Continue before delivering the request callback.
on_body
on_body => sub {
my ($tx, $request, $bytes) = @_;
}
Called zero or more times as request body bytes arrive.
HTTP transfer framing such as chunk boundaries has already been removed. Content codings such as gzip are not decoded automatically.
The same Transaction and Request objects are used for every body callback of the request.
on_request_end
on_request_end => sub {
my ($tx, $request) = @_;
}
Called once after the complete request body and any trailers have arrived.
Before this callback runs, the request is marked complete and frozen. Trailer fields are available through the Uniform request object.
A request with no body reaches on_request_end immediately after on_request returns.
on_error
on_error => sub {
my ($tx, $error) = @_;
}
Called for a server-side HTTP or application failure.
$tx may be undef when the failure happened before a transaction could be created, or when a transport failure affects an otherwise idle connection.
Examples include malformed framing, head limits, unexpected EOF, callback exceptions, and explicit transport failure.
When an application callback dies before a response has started, the engine attempts to produce a 500 response and closes the HTTP connection.
Protocol errors produce an appropriate HTTP error response when possible and close the connection.
on_switch
on_switch => sub {
my ($tx, $response) = @_;
}
Called when a sent 101 response or successful CONNECT transfers ownership of the connection away from HTTP.
At this point is_switched() is true. Any bytes already read beyond the HTTP boundary are available through take_remainder().
RESPONDING
on_request receives an Unblock::HTTP1::Transaction. Normal responses can be created directly:
$tx->respond(
status => 200,
headers => [
[ 'Content-Type' => 'text/plain' ],
],
body => "hello\n",
);
respond() constructs the canonical Uniform::HTTP::Response internally.
An existing response object is also accepted:
$tx->respond($response);
Informational responses use:
$tx->send_informational(
status => 103,
headers => [
[ Link => '</style.css>; rel=preload' ],
],
);
Informational responses must be 100 through 199 except 101. HTTP/1.0 clients cannot receive informational responses through this method.
STREAMING RESPONSES
To produce a response body incrementally:
$tx->respond(
status => 200,
stream_body => 1,
on_drain => sub {
produce_more();
},
);
my $ok = $tx->write($chunk);
$tx->end($last_chunk);
For HTTP/1.1, chunked transfer framing is used when required. An explicit Content-Length is honored and enforced. HTTP/1.0 streaming may require close-delimited framing or an explicit length depending on the response.
A false return from write() means the bytes were accepted but the producer should pause. on_drain runs when the output path becomes writable again.
Known response trailers are serialized with the final chunk. If trailer names will only be known later, the application should predeclare allowed trailer names in the response Trailer field.
TRANSACTION
transaction
my $tx = $server->transaction;
Returns the currently active transaction, or undef when the server is idle.
Because requests are processed serially on one HTTP/1 connection, this method never returns a later pipelined transaction while an earlier one is active.
CONNECTION INPUT
input
my $accepted = $server->input($bytes);
Feeds received request bytes into the engine.
The return value is the number of supplied bytes accepted by the portable input path.
The engine may invoke request callbacks before input() returns.
Do not call input() recursively from an HTTP callback.
input_eof
$server->input_eof;
Reports a clean read-side EOF. Unlike a transport error, a fully received request may still receive a delayed response after EOF. An incomplete request at EOF is handled as an HTTP framing error. Do not use input('') as EOF.
transport_error
$server->transport_error($reason);
Reports a broken socket, TLS failure, or other unusable transport. Unsent HTTP output is discarded; outstanding work fails and unblock_abort() is called. Do not call this on ordinary read-side EOF.
CONNECTION OUTPUT
want_write
$server->want_write;
True when the engine has bytes buffered for output.
Normally unnecessary when an attached transport is present.
output
my $bytes = $server->output;
my $bytes = $server->output($maximum);
Removes and returns queued wire bytes in manual integration mode. output() throws when a transport is attached to prevent mixed ownership.
$maximum, when supplied, must be a positive integer.
Draining below the low-water mark can resume a blocked streaming response and invoke its on_drain callback.
Do not call output() recursively from an HTTP callback.
resume_output
$server->resume_output;
Called by an attached host after unblock_send() returned a defined false value (meaning complete acceptance followed by congestion). The host must call this again when it can accept more output. It can trigger a streaming Transaction's on_drain callback.
A fatal host write error is not ordinary congestion. A transport such as Linux::Event may close itself on an output hard-limit violation. The host adapter must report the error to the engine (or throw from unblock_send()); it must not return false as though the rejected bytes were accepted, nor call resume_output() for that rejected output.
With an attached host, normal server transaction on_finish success waits until all its outgoing HTTP bytes have been accepted by the host, including batched pipelined responses. If the host rejects that queued output, the pending Transactions finish with error instead. Acceptance means ownership transfer to the host, not that the remote peer has received the bytes. Manual output() use retains its original local-completion timing.
An output-queueing host that always returns undef does not need it.
CONNECTION STATE
want_read
$server->want_read;
True while the engine is still accepting HTTP bytes.
It becomes false after read EOF, close, or protocol switch.
is_closed
$server->is_closed;
True when the HTTP connection is closed.
is_switched
$server->is_switched;
True after a 101 response or successful CONNECT transfers ownership away from HTTP.
take_remainder
my $bytes = $server->take_remainder;
Returns bytes already received after the HTTP boundary.
Valid only after is_switched() becomes true.
close
$server->close;
$server->close($reason);
Closes the HTTP engine and fails unfinished work.
With an attached transport, already queued HTTP output is handed to the transport before graceful close when possible.
Use transport_error() instead when the transport itself has failed.
KEEP-ALIVE AND PIPELINING
HTTP/1 persistence is managed by the engine from the request and response framing rules.
If a connection is reusable, the server returns to idle state after the active transaction retires.
If later request bytes were already received, they remain buffered and the next request is parsed after the prior transaction completes. Application code does not need to coordinate pipelined byte boundaries.
PROTOCOL SWITCH
A 101 response or successful CONNECT ends HTTP framing on this connection.
The Transaction completes first, then on_switch runs. When a transport is attached, the switch callback runs only after the outgoing handshake bytes have been accepted by the host. They may still be waiting in the host's own write queue.
After the switch:
$server->is_switched;
is true and:
my $tail = $server->take_remainder;
returns bytes which belong to the next protocol.
Do not continue feeding those bytes to HTTP.
CALLBACK ERRORS AND REENTRANCY
Exceptions thrown by server callbacks are treated as connection/application errors.
Application callbacks may call Transaction methods such as respond(), write(), and end().
Do not recursively call input(), input_eof(), or output() from an engine callback.
TRANSACTION OBJECTS
The Transaction provides:
request
response
respond
send_informational
write
end
cancel
state
error
is_complete
is_cancelled
is_error
is_terminal
See Unblock::HTTP1::Transaction for details.
NATIVE INPUT
XS-backed transports can use Unblock::HTTP1::NativeABI to feed borrowed native buffers directly.
Native input uses the same Server object and HTTP callbacks.
SEE ALSO
Unblock::HTTP1::Integration, Unblock::HTTP1, Unblock::HTTP1::Transaction, Unblock::HTTP1::NativeABI, Uniform::HTTP::Request, Uniform::HTTP::Response