Unblock::HTTP1
Unblock::HTTP1 is a non-blocking HTTP/1.0 and HTTP/1.1 protocol engine for Perl.
It parses requests, serializes responses, handles HTTP message boundaries, streaming bodies, keep-alive, trailers, Upgrade, and CONNECT.
It does not open sockets, do DNS or TLS, run an event loop, or manage connection pools. It can be hosted by IO::Async, AnyEvent, Linux::Event, Mojolicious, native transport code, or another event framework.
Installation
cpanm Unblock::HTTP1
Version 0.11 requires Perl 5.16 and Uniform::HTTP 0.06 or newer. Linux::Event, IO::Async and AnyEvent are optional host frameworks.
Start here
The three application classes are:
- Unblock::HTTP1::Client - one client-side connection
- Unblock::HTTP1::Server - one server-side connection
- Unblock::HTTP1::Transaction - one request and response exchange
A transaction uses the shared Unblock vocabulary: respond(), write(), end(), send_informational(), state(), error(), is_complete(), is_cancelled(), is_error(), and is_terminal().
The easiest server response:
$tx->respond(
status => 200,
body => "Hello World!\n",
);
The easiest client request:
$client->request(
method => 'GET',
target => '/',
authority => 'example.test',
on_response => sub {
my ($tx, $response) = @_;
print $response->status, "\n";
},
);
These calls still create and use canonical Uniform::HTTP::Request and Uniform::HTTP::Response messages internally. Existing Uniform objects continue to work directly:
$client->request($request);
$tx->respond($response);
Connect to an event framework
Create one Client or Server per framework connection:
$self->{http1} = Unblock::HTTP1::Server->new(
transport => $self,
on_request => $on_request,
);
The framework object implements only three host methods:
unblock_send($bytes) # accept complete output into framework queue
unblock_finish() # graceful close after queued output
unblock_abort($reason) # immediate failure close
The framework feeds incoming events to the engine:
$http->input($bytes);
$http->input_eof;
$http->transport_error($reason);
The engine delivers output automatically. A delayed response from a timer or database callback also triggers output without another framework read event.
An integration that exposes congestion returns false from unblock_send() AFTER accepting the whole buffer, and later calls $http->resume_output. If the framework simply queues all output, it may return undef.
The engine holds a weak reference to the host. The framework owns its sockets, output queue, and loop.
Full working server and client examples:
- examples/io-async-server.pl
- examples/io-async-client.pl
- examples/anyevent-server.pl
- examples/anyevent-client.pl
- examples/linux-event-server.pl
The examples separate adapter code from application code. The Linux::Event server demonstrates the same host API using a Stream subclass and a separate application subclass. Linux::Event is not a required dependency.
For complete instructions, read:
perldoc Unblock::HTTP1::Integration
The repository also includes docs/INTEGRATION.md and docs/COOKBOOK.md.
Connection and message behavior
A Client queues requests serially on one connection; it does not silently enable HTTP/1 pipelining. A Server can receive pipelined request bytes and process them in HTTP order.
A server's on_request runs after the request head has arrived. on_body delivers decoded request body fragments. on_request_end runs when the full request, including trailers, is complete.
For a streaming response:
$tx->respond(status => 200, stream_body => 1);
$tx->write($chunk);
$tx->end($final_bytes);
write() and end() accept bytes even when they return false for backpressure. Use on_drain to resume producing data.
A clean read EOF is not the same as fatal transport failure. After a fully received request, the server can still send a delayed response, then close gracefully.
A 101 Upgrade response or successful CONNECT switches away from HTTP. take_remainder() returns already-received bytes belonging to the next protocol. An attached server invokes on_switch after the full outgoing HTTP handshake has been accepted into the framework's write queue.
Manual and native integration
For advanced consumers, the original low-level output interface remains:
$http->input($bytes);
while ($http->want_write) {
$transport->write($http->output);
}
This is for engines built WITHOUT an attached transport. Do not mix manual output draining and automatic output ownership.
XS-backed transports can use Unblock::HTTP1::NativeABI v1 to pass borrowed native input. The ABI is input-side and remains transport neutral. It supports the same HTTP callbacks and can construct canonical Uniform messages through Uniform::HTTP 0.06's native FastPath.
The installed C header is:
Unblock/HTTP1/NativeABI/unblock_http1_native_abi.h
ABI discovery:
Unblock::HTTP1::NativeABI::definition()
Unblock::HTTP1::NativeABI::native_include_dir()
Unblock::HTTP1::NativeABI::header_path()
Unblock::HTTP1::NativeABI::c_header()
Limits
Defaults:
max_head_size 65536 bytes
max_headers 100
max_chunk_extension_size 16384 bytes
high_water 65536 bytes
low_water 32768 bytes
See docs/PROTOCOL_STATUS.md for the protocol feature checklist.
License
MIT License.