# Unblock::HTTP3

[![CPAN version](https://badge.fury.io/pl/Unblock-HTTP3.svg)](https://metacpan.org/dist/Unblock-HTTP3)
[![CPANTS Kwalitee](https://cpants.cpanauthors.org/dist/Unblock-HTTP3.svg)](https://cpants.cpanauthors.org/dist/Unblock-HTTP3)
[![CI](https://github.com/haxmeister/perl-Unblock-HTTP3/actions/workflows/test.yml/badge.svg?branch=main)](https://github.com/haxmeister/perl-Unblock-HTTP3/actions/workflows/test.yml)
[![HTTP/3 interop](https://github.com/haxmeister/perl-Unblock-HTTP3/actions/workflows/interop.yml/badge.svg?branch=main)](https://github.com/haxmeister/perl-Unblock-HTTP3/actions/workflows/interop.yml)
[![License](https://img.shields.io/cpan/l/Unblock-HTTP3.svg)](https://github.com/haxmeister/perl-Unblock-HTTP3/blob/main/LICENSE)
[![Perl](https://img.shields.io/badge/perl-5.20%2B-blue.svg)](https://www.perl.org/)

Unblock::HTTP3 is a non-blocking HTTP/3 protocol engine for Perl.

It handles HTTP/3 framing, QPACK, request streams, trailers, informational
responses, Extended CONNECT, HTTP Datagrams, Capsules, priorities, graceful
shutdown, and replay-aware 0-RTT state.

It does not own UDP sockets, TLS, timers, or an event loop. Net::QUIC owns the
QUIC transport.

```text
application or HTTP library
        |
  Uniform::HTTP messages
        |
   Unblock::HTTP3
        |
      Net::QUIC
        |
        UDP
```

## Installation

From CPAN:

```text
cpanm Unblock::HTTP3
```

Unblock::HTTP3 0.10 requires:

```text
Perl            5.20+
Alien::nghttp3  0.01+
Net::QUIC       0.04+
Uniform::HTTP   0.06+
```

Version 0.10 intentionally breaks the earlier 0.03 Perl API. Client and Server
now use `new()`, final responses use `respond()`, and the old
`Connection->client()`, `Connection->server()`, and `send_response()`
entry points are removed. There are no compatibility aliases.

## Start here

The public API is built around three objects:

- `Unblock::HTTP3::Client` - one client HTTP/3 connection
- `Unblock::HTTP3::Server` - one server HTTP/3 connection
- `Unblock::HTTP3::Transaction` - one request and response exchange

The common application vocabulary intentionally matches the other Unblock HTTP
engines:

```text
Client->new
Server->new
request()
respond()
write()
end()
send_informational()
```

HTTP/3 protocol concepts keep their HTTP/3 names.

Exact canonical `Uniform::HTTP::Request` and `Uniform::HTTP::Response`
objects use the Uniform::HTTP native fast path. Uniform-compatible adapters and
subclasses use the portable Perl message contract.

## Client

```perl
use Uniform::HTTP::Request;
use Unblock::HTTP3::Client;

my $client = Unblock::HTTP3::Client->new(
    quic => $quic,
);

$client->start;

my $transaction = $client->request(
    Uniform::HTTP::Request->new(
        method    => 'GET',
        target    => '/',
        scheme    => 'https',
        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";
    },
);
```

Many Transactions can be active on one Client at the same time.

The existing pull interface remains available through `next_transaction()`
and `next_informational()` for integrations that prefer polling.

## Server

```perl
use Uniform::HTTP::Response;
use Unblock::HTTP3::Server;

my $server = Unblock::HTTP3::Server->new(
    quic => $quic,

    on_request => sub {
        my ($transaction, $request) = @_;

        $transaction->respond(
            Uniform::HTTP::Response->new(
                status => 200,
                body   => "hello\n",
            ),
        );
    },
);

$server->start;
```

`on_body` receives request body chunks. `on_request_end` runs after the
request body and trailers have completed.

## Streaming bodies

Buffered bodies can live directly on the Uniform message object.

For a streaming client request:

```perl
my $transaction = $client->request(
    $request,
    stream_body => 1,
    on_drain => sub {
        my ($transaction) = @_;
        produce_more($transaction);
    },
);

$transaction->write($chunk);
$transaction->end($last_chunk);
```

A streaming server response uses the same Transaction API:

```perl
$transaction->respond(
    $response,
    stream_body => 1,
    on_drain => sub {
        my ($transaction) = @_;
        produce_more($transaction);
    },
);

$transaction->write($chunk);
$transaction->end;
```

For advanced HTTP/3 body control, `Body::Stream` and `Body::Reader` remain
available. They expose explicit receive credit, cancellation, and body-specific
callbacks without changing the common Transaction API.

## Informational responses

A server can send a 1xx response before the final response:

```perl
$transaction->send_informational(
    Uniform::HTTP::Response->new(
        status => 103,
    ),
);

$transaction->respond($final_response);
```

HTTP/3 does not use status 101.

## Transaction state

The common lifecycle methods are:

```text
state
error
is_complete
is_cancelled
is_error
is_terminal
```

HTTP/3-specific reset and STOP_SENDING details remain available separately on
the Transaction.

## CONNECT, Capsules, and Datagrams

Ordinary CONNECT and generic Extended CONNECT are supported.

Extended CONNECT uses the Uniform `protocol` field. Higher-level modules
decide what a protocol such as WebSocket, WebTransport, or MASQUE means.

An Extended CONNECT Transaction can use the RFC 9297 Capsule Protocol through:

```perl
my $capsules = $transaction->capsules;
```

RFC 9297 HTTP Datagrams use Net::QUIC DATAGRAM support. Enable them on the
Client or Server with:

```perl
enable_http_datagrams => 1
```

A client marks a request as using Datagrams with:

```perl
my $transaction = $client->request(
    $request,
    datagrams => 1,
);
```

The Transaction provides `send_datagram()`, `next_datagram()`,
`on_datagram()`, and `max_datagram_payload_size()`.

## Priority and ORIGIN

RFC 9218 priority state is available through `Transaction->priority()`.

Servers can advertise RFC 9412 origins with the `origins` constructor option.
Clients read the received set with `peer_origins()`.

## 0-RTT

Net::QUIC owns QUIC/TLS early-data state. Unblock::HTTP3 owns the remembered
HTTP/3 SETTINGS needed to validate early requests.

Save the QUIC and HTTP/3 state from the same successful session:

```perl
my $quic_state = $quic->early_data_state;
my $h3_state   = $client->peer_settings_state;
```

An early client request must opt in explicitly:

```perl
my $transaction = $client->request(
    $request,
    early_data => 1,
);
```

0-RTT can be replayed. Unblock::HTTP3 does not automatically retry a rejected
early request.

## Native integrations

XS event frameworks and HTTP libraries can use
`Unblock::HTTP3::NativeABI`.

Native integrations can discover the installed ABI with:

```text
definition
native_include_dir
header_path
c_header
```

ABI version 1 accepts exact `Unblock::HTTP3::Client`,
`Unblock::HTTP3::Server`, and `Unblock::HTTP3::Transaction` objects.
Adapters and subclasses use the portable Perl API.

The native ABI does not expose libnghttp3 internals and does not take ownership
of the QUIC transport.

See `docs/NATIVE-ABI.md`.

## What Unblock::HTTP3 does not own

Unblock::HTTP3 does not own:

- UDP sockets
- DNS
- TLS
- QUIC packet processing
- congestion control
- retransmission
- connection migration
- timers
- event loops
- connection pools
- redirects
- cookies
- authentication policy
- retry policy
- WebSocket, WebTransport, or MASQUE semantics

Those belong to Net::QUIC, the event-loop adapter, the application, or a
higher-level protocol module.

## Testing

The normal suite uses real kernel UDP sockets, TLS, QUIC, and HTTP/3.

CI tests released dependencies on several Perl versions and validates the built
distribution. Separate interoperability tests cover both client and server
directions against independent HTTP/3 implementations.

## More documentation

- `Unblock::HTTP3::Client`
- `Unblock::HTTP3::Server`
- `Unblock::HTTP3::Transaction`
- `Unblock::HTTP3::Body::Stream`
- `Unblock::HTTP3::Body::Reader`
- `Unblock::HTTP3::NativeABI`
- `docs/ARCHITECTURE.md`
- `docs/NATIVE-ABI.md`
- `docs/RFC-COMPLIANCE.md`

## License

MIT.
