Unblock::HTTP1
Unblock::HTTP1 is a non-blocking HTTP/1 protocol engine for Perl.
It handles HTTP/1.0 and HTTP/1.1 parsing, serialization, framing, streaming bodies, persistent connections, informational responses, trailers, Upgrade, and CONNECT.
It does not open sockets, perform DNS or TLS, choose an event loop, or manage connection pools.
application or HTTP library
|
Uniform::HTTP messages
|
Unblock::HTTP1
|
byte transport
The transport can be Linux::Event, IO::Async, AnyEvent, Mojolicious, a blocking socket, an in-memory test connection, or something else.
Installation
From CPAN:
cpanm Unblock::HTTP1
Unblock::HTTP1 0.10 requires Perl 5.16 or newer and Uniform::HTTP 0.06 or newer.
Version 0.10 intentionally joins the common Unblock HTTP API vocabulary while the distributions are still young. No compatibility aliases are carried.
Start here
The public API is built around three objects:
Unblock::HTTP1::Client- one client HTTP/1 connectionUnblock::HTTP1::Server- one server HTTP/1 connectionUnblock::HTTP1::Transaction- one request/response exchange
HTTP messages are normal Uniform::HTTP::Request and
Uniform::HTTP::Response objects.
The application-facing vocabulary is intentionally shared with the other Unblock HTTP engines:
Client->new
Server->new
request()
respond()
write()
end()
send_informational()
Transactions use the common lifecycle vocabulary:
state()
error()
is_complete()
is_cancelled()
is_error()
is_terminal()
The basic transport contract is byte-in, byte-out:
$engine->input($bytes_from_transport);
while ($engine->want_write) {
my $bytes = $engine->output;
last unless length $bytes;
$transport->write($bytes);
}
Unblock::HTTP1 never waits for network activity itself.
Client
use Uniform::HTTP::Request;
use Unblock::HTTP1::Client;
my $client = Unblock::HTTP1::Client->new;
my $transaction = $client->request(
Uniform::HTTP::Request->new(
method => 'GET',
target => '/',
authority => 'example.com',
),
on_response => sub {
my ($transaction, $response) = @_;
print $response->status, "\n";
},
on_body => sub {
my ($transaction, $response, $bytes) = @_;
process_bytes($bytes);
},
on_complete => sub {
my ($transaction) = @_;
print "done\n";
},
);
A Client serializes requests on one connection. It does not silently enable HTTP/1 pipelining.
Server
use Uniform::HTTP::Response;
use Unblock::HTTP1::Server;
my $server = Unblock::HTTP1::Server->new(
on_request => sub {
my ($transaction, $request) = @_;
$transaction->respond(
Uniform::HTTP::Response->new(
status => 200,
body => "hello\n",
),
);
},
);
Request bodies arrive through on_body. on_request_end runs after the
complete request body and trailers have arrived.
Streaming bodies
For a streaming client request:
my $transaction = $client->request(
$request,
stream_body => 1,
);
$transaction->write($chunk);
$transaction->end($last_chunk);
For a streaming server response:
$transaction->respond(
$response,
stream_body => 1,
);
$transaction->write($chunk);
$transaction->end($last_chunk);
HTTP/1.1 uses chunked framing when needed. HTTP/1.0 streaming requires an explicit Content-Length.
write() returns false when the engine output queue reaches its high-water
mark. on_drain fires after the queue falls below its low-water mark.
Informational responses
A server Transaction can send a 1xx response before its final response:
$transaction->send_informational($response);
$transaction->respond($final_response);
Upgrade and CONNECT
A 101 response or successful CONNECT ends HTTP framing on the connection.
The engine then reports:
$engine->is_switched
Bytes already read after the HTTP boundary are preserved:
my $bytes = $engine->take_remainder;
The caller can pass those bytes to the next protocol implementation.
Native integration
The normal input() method remains the portable path.
XS-backed transports can optionally use Unblock::HTTP1::NativeABI to feed
borrowed native input buffers directly. The transport keeps ownership of the
input storage and Unblock reports the permanently consumed prefix.
Canonical Uniform::HTTP 0.06 messages use the Uniform native construction path on this route.
Native integrations can discover the installed ABI with:
my $definition = Unblock::HTTP1::NativeABI::definition();
my $include_dir = Unblock::HTTP1::NativeABI::native_include_dir();
my $header_path = Unblock::HTTP1::NativeABI::header_path();
my $header = Unblock::HTTP1::NativeABI::c_header();
The installed public header is:
Unblock/HTTP1/NativeABI/unblock_http1_native_abi.h
HTTP/1 keeps its native ABI focused on borrowed input. It does not add HTTP/2-specific native output operations merely for API symmetry.
See docs/INTEGRATION.md for the transport contract and ownership rules.
Limits
Default limits are:
maximum HTTP head: 65536 bytes
maximum header fields: 100
maximum chunk extension bytes: 16384 per message
output high water: 65536 bytes
output low water: 32768 bytes
The limits can be changed when constructing a Client or Server.
Protocol status
The HTTP/1 protocol engine is complete for its declared scope and has cross-platform CI coverage on Linux, macOS, and Windows, including Perl 5.16.
See docs/PROTOCOL_STATUS.md for the detailed protocol checklist.
License
MIT License.