# Unblock::HTTP1 [![Tests](https://github.com/haxmeister/perl-Unblock-HTTP1/actions/workflows/test.yml/badge.svg)](https://github.com/haxmeister/perl-Unblock-HTTP1/actions/workflows/test.yml) [![CPAN](https://img.shields.io/cpan/v/Unblock-HTTP1.svg)](https://metacpan.org/release/Unblock-HTTP1) [![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) 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.