NAME

Linux::Event::HTTP::Client - asynchronous HTTP client

SYNOPSIS

use HTTP::CookieJar;
use Uniform::HTTP::Auth;

my $jar = HTTP::CookieJar->new;
my $auth = Uniform::HTTP::Auth->new(
    credentials => sub ($context) {
        return lookup_credentials($context);
    },
);

my $client = Linux::Event::HTTP::Client->new(
    loop => $loop,
    max_redirects => 5,
    max_auth_retries => 3,
    proxy => 'http://proxy.example:3128',
    cookie_jar => $jar,
    auth => $auth,
    proxy_auth => $auth,
);

my $operation = $client->get(
    'https://example.com/start',
    on_redirect => sub ($op, $tx, $res, $next_url) {
        say "redirecting to $next_url";
    },
    on_complete => sub ($tx) {
        say $tx->response->status;
    },
    on_error => sub ($tx, $error) {
        warn $error;
    },
);

DESCRIPTION

Linux::Event::HTTP::Client is the high-level outbound HTTP entry point. It owns URL parsing, destination selection, redirect and authentication retry policy, connection creation, HTTPS transport policy, explicit forward-proxy routing, optional cookie-jar integration, and a small bounded reuse policy.

Authentication mechanics are delegated to Uniform::HTTP::Auth. The Client only receives 401/407 responses, supplies the exact Request object and protection-space origin, decides whether a Request is replayable, and performs the retry as another Transaction.

Client methods return Linux::Event::HTTP::Client::Operation. An operation normally contains one Linux::Event::HTTP::Transaction, but redirects and automatic authentication retries create additional Transactions because a Transaction always represents exactly one Request/Response exchange.

Outgoing Request bodies may be complete scalar bodies or explicit streaming producers owned by Transaction. Incoming Response handling remains incremental-first. on_body consumes body chunks. Without on_body, body bytes are drained and discarded. Explicit buffer_body => $max_bytes requests bounded whole-body buffering; there is no implicit unbounded buffering.

METHODS

request

my $operation = $client->request(
    'POST',
    'https://example.com/api/items',
    body => $bytes,
    max_redirects => 5,
    max_auth_retries => 3,
    on_response => sub ($tx, $res) { ... },
    on_complete => sub ($tx) { ... },
    on_error => sub ($tx, $error) { ... },
);

Builds the canonical Request for each exchange and starts the operation immediately. Only absolute http and https target URLs are accepted.

Without a selected proxy, the Client obtains or creates a connection for the target URL origin and sends the path/query in origin-form. With a selected proxy, it connects to that route and sends the target URL in HTTP/1 absolute-form. Host remains the target Host. Target identity and route identity remain separate.

Callbacks on_response, on_body, and on_complete describe the final response. Intermediate redirect and authentication-challenge response bodies are consumed according to normal HTTP framing but are not delivered through on_body. on_redirect runs only for actual redirects, not auth retries.

authentication

my $auth = Uniform::HTTP::Auth->new(
    credentials => sub ($context) {
        return $store->lookup(
            $context->{origin},
            $context->{realm},
            $context->{scheme},
        );
    },
);

my $client = Linux::Event::HTTP::Client->new(
    loop => $loop,
    auth => $auth,
    proxy_auth => $auth,
);

auth handles target-server 401 challenges from WWW-Authenticate. proxy_auth handles proxy 407 challenges from Proxy-Authenticate. They may be different Uniform::HTTP::Auth objects or the same callback-based object. Both options can be overridden per ordinary request with another object or explicitly disabled for that request with undef.

The Client passes the normalized target or proxy origin and the actual Linux::Event::HTTP::Request to Uniform::HTTP::Auth 0.02. Request implements the Uniform message contract directly, so authentication reads its exact method, request-target, and buffered scalar body without consuming an incremental body producer. The returned value is installed as Authorization or Proxy-Authorization on a new Transaction.

Authentication responses are drained to their normal HTTP message boundary before retry. A retry may reuse the persistent connection when framing and connection state permit it, or establish another connection when necessary. A proxy-authenticated request can subsequently receive a target 401; the target authentication retry preserves the proxy field for that same request-target.

Generated authentication fields are attempt-local. They are not copied across redirects because Digest authentication incorporates request-target state and Uniform::HTTP::Auth 0.02 does not provide a preemptive-auth cache. A redirected target or proxy can challenge again normally.

Streaming Request producers are not replayed automatically. If a satisfiable 401/407 challenge is received for a streaming Request, the operation terminates with an error rather than guessing how to rewind application state.

max_auth_retries defaults to 3 and is an operation-wide bound separate from max_redirects. Zero disables automatic challenge retry and exposes 401/407 as ordinary final responses. When the limit is reached, the next challenge is also exposed as the final response rather than retried again.

When auth is configured, caller-supplied Authorization is rejected for that request. Likewise proxy_auth owns Proxy-Authorization. Disable the corresponding manager for a request if manually constructing that field.

The auth, proxy_auth, and max_auth_retries accessors return the Client defaults.

cookie_jar is an optional injected HTTP::CookieJar. The Client does not create a jar implicitly. Before each ordinary Request exchange the Client asks the jar for cookie_header($target_url) and feeds every Response Set-Cookie field back through add($target_url,$value) before redirect/authentication policy or application callbacks run.

Cookie identity is always the target URL. A selected proxy never becomes the cookie origin. When cookie_jar is configured, caller-supplied Cookie fields are rejected so cookie selection has one owner. The cookie_jar accessor returns the configured jar object or undef.

connect_tunnel

connect_tunnel($proxy_url, $target_authority, ...) establishes one explicit HTTP/1.1 CONNECT tunnel through the named proxy endpoint. The Client-level default proxy and cookie jar are not consulted for tunnel routing or cookies. The Client-level proxy_auth is consulted by default for 407 challenges and can be overridden or disabled with the method's proxy_auth option.

A successful 2xx response transitions the same live Linux::Event stream to the required tunnel_to class. Non-2xx responses remain ordinary HTTP. A satisfiable 407 can be drained and retried as another CONNECT Transaction before that final outcome.

redirect policy

max_redirects is a non-negative integer and defaults to 5. It can be set on the Client or overridden per request. Zero disables automatic redirect following. Automatic redirects recognize 301, 302, 303, 307, and 308 when exactly one Location field is present.

301 and 302 change POST to GET and discard the body. 303 uses GET, or HEAD when the original method was HEAD, and discards the body. 307 and 308 preserve the method and body. Complete scalar bodies can be replayed for method-preserving redirects; streaming bodies are not replayed automatically.

Authorization and caller-managed Cookie fields are stripped on cross-origin redirects. With cookie_jar, Cookie is regenerated independently for every hop from the new target URL. Uniform-managed Authorization and Proxy-Authorization fields are attempt-local and are regenerated only after a new challenge.

request bodies

body supplies a complete scalar Request body. stream_body => { ... } selects incremental body production instead; the two are mutually exclusive. The producer belongs to the current Transaction and is available through the returned operation.

A supplied Content-Length is enforced exactly; otherwise HTTP/1.1 uses chunked transfer coding automatically. HTTP/1.0 streaming requires Content-Length.

client Upgrade

upgrade_to => $class requests a live HTTP/1.1 protocol handoff through the low-level Client::Connection. On a validated 101 response, the HTTP Transaction completes and the same live stream transitions to $class. Authentication challenges may precede the successful 101 when the Request is otherwise replayable.

buffer_body

buffer_body => $max_bytes requests bounded whole-response buffering and cannot be combined with on_body. The limit applies after HTTP transfer framing has been removed and also applies while redirect or authentication challenge bodies are consumed.

get, head, post, put, delete

Convenience forms that call request with the corresponding HTTP method.

loop

Returns the Linux::Event Loop.

connection_class

Returns the configured Client::Connection class.

max_redirects

Returns the Client default redirect limit.

max_auth_retries

Returns the Client default automatic authentication retry limit.

proxy

Returns the configured Client default forward-proxy URL, or undef when there is no default proxy. An individual operation may override or bypass the default.

auth

Returns the configured default target Uniform::HTTP::Auth object or undef.

proxy_auth

Returns the configured default proxy Uniform::HTTP::Auth object or undef.

is_closed

True after close.

close

Closes all reachable idle or active client connections and prevents new requests. Returns the Client.

CONNECTION REUSE

At most one idle connection is retained per route origin. For direct requests, the route origin is the target origin. For a request using a proxy route, the route origin is the proxy endpoint, so sequential requests for different target origins can reuse the same persistent proxy connection. Cookie and target-auth selection do not use route origin; proxy authentication does.

A connection that successfully leaves HTTP through Upgrade or CONNECT is never returned to the HTTP idle pool. A non-2xx CONNECT response remains HTTP and may leave a reusable proxy connection when its normal response framing permits it.

HTTPS

HTTPS uses the same Client::Connection class with a Linux::Event TLS transport. For a direct HTTPS request, TLS is established to the target URL host. For an https forward-proxy endpoint, TLS is established to the proxy and the target URI is then sent in absolute-form. Cookie and target-auth origin identity remain the target URL; proxy-auth origin identity remains the proxy endpoint.

SEE ALSO

Uniform::HTTP::Auth, HTTP::CookieJar, Linux::Event::HTTP::Client::Operation, Linux::Event::HTTP::Client::Connection, Linux::Event::HTTP::Request, Linux::Event::HTTP::Response, Linux::Event::HTTP::Transaction, Linux::Event::HTTP::Body::Stream.