NAME

UniEvent::HTTP::Request - HTTP client request class

SYNOPSIS

# explicit creation
my $request = UE::HTTP::Request->new({
    uri => "http://example.com",
    timeout => 3,
    response_callback => sub {
        my ($request, $response, $error) = @_;
        ...
    },
});

http_request($request);

# implicit creation
http_request({
    uri => "http://example.com",
    timeout => 3,
    response_callback => sub {
        my ($request, $response, $error) = @_;
        ...
    },
});

DESCRIPTION

UniEvent::HTTP::Request is used to make client http requests. It holds all the properties and state of http request. UniEvent::HTTP::Request object is passed then to http_request(), http_request_sync(), $pool->request, $client->request or $user_agent->request functions.

Once completed, a Request object can be used again to make another http request. However one request object cannot be run twice at a time.

UniEvent::HTTP::Request inherits from Protocol::HTTP::Request. So for complete documenation you need to also read Protocol::HTTP::Request's docs.

Request supports chunked transmission. If you set chunked property (see Protocol::HTTP::Request) to a true value, then after you send this request via http_request(), etc... you will need to send http chunks via send_chunk() method and then send_final_chunk() when you are done.

Request supports compression. There is nothing to do and document here about compression as everything is implemented and documented in Protocol::HTTP.

Request supports real-time partial body receival for streaming into storage without memory consumption or incremental parsing of sub-protocol. See partial_callback().

See detailed description in corresponding method docs.

METHODS

All methods of Protocol::HTTP::Request also apply.

new(\%params)

Constructs a request object from hashref of params.

This method is also called implicitly when you pass hashref of params to functions like http_request(), $pool->request and so on, i.e. where an object of UniEvent::HTTP::Request is expected.

Params can contain:

All params from Protocol::HTTP::Request::new() also apply
timeout [=20]
follow_redirect [=true]
redirection_limit [=20]
tcp_nodelay [=false]
tcp_hints
ssl_ctx
proxy
response_callback
partial_callback
redirect_callback
continue_callback

See corresponding description of all parameters above in their setter-getter methods below.

form

Although Protocol::HTTP::Request::new() supports the form parameter, UniEvent::HTTP::Request extends its possibilities to support real-time streaming of data to form.

Form fields values from Protocol::HTTP::Request are required to be available upfront, i.e.:

my $pdf_content = ...; # obtain file content somehow
form => [
    'key1' => $value1,
    'key2' => ['a.pdf' => $pdf_content, 'application/pdf'],
    ...
]});

In the UniEvent::HTTP it is possible to specify any input stream, which will push bytes lately, as soon as they become available. Usually, this file input, but the data can be also be taken from TCP connection via UniEvent::Streamer::StreamInput. This way it is possible to avoid reading huge files in-memory before streaming them to peer.

my $pdf_content = UE::Streamer::FileInput->new("path/to/my.pdf");
form => [
    'key1' => $value1,
    'key2' => ['a.pdf' => $pdf_content, 'application/pdf'],
    ...
]});

The streaming is availabe only for multipart/form-data method of posting data. In other words, multipart/form-data will always be forced for you, if any streaming content is detected.

NOTE: If you create your own request class inherited from UniEvent::HTTP::Request, you must proxy to original new() method and use its result as an object you return. By default it is a reference to undef, you can upgrade it to hash-based object via XS::Framework::obj2hv:

package MyRequest;
use parent 'UniEvent::HTTP::Request';

sub new {
    my $class = shift;
    my $self = $class->SUPER::new(@_);
    XS::Framework::obj2hv($self);
    $self->{prop} = "val";
    return $self;
}

timeout([$timeout])

Get/set timeout for the whole request (connect + sending request + receiving response) in seconds (can be fractional). To disable timeout, set zero.

If time is up, request will finish with error UniEvent::SystemError::timed_out.

follow_redirect([$bool])

Get/set follow_redirect flag.

If set to true and the server's response code is one of 300, 301, 302, 303, 307 or 308, will transparently make another request to the destination described in response and use that another response.

New request will be made to a location specified in Location header in the response. Headers Authorization, Cookie, Referer in original request get removed for security reasons; so does ssl_ctx if ssl is in use. If precise control over this process is needed, consider setting redirect_callback (see docs below).

If new response is a redirection again, will repeat this procedure up to redirection_limit times. If this limit is exceeded, request will finish with error UniEvent::HTTP::Error::redirection_limit. If the limit is set to 0, then request will finish with error UniEvent::HTTP::Error::unexpected_redirect immediately on first redirection response.

If set to false, then just content of redirection response will be returned.

redirection_limit([$cnt])

Get/set redirection limit, see follow_redirect().

tcp_nodelay([$bool])

Get/set tcp nodelay feature.

tcp_hints([$hints])

Get/set DNS resolving hints. Hints can be used to disambiguate domain name resolution in certain cases. $hints should be either a binary string created via UniEvent::Resolver::hints()

$request->tcp_hints(UniEvent::Resolver::hints(AF_INET, SOCK_STREAM, PF_INET));

Or a hashref with the corresponding info

$request->tcp_hints({
    family   => AF_INET,
    socktype => SOCK_STREAM,
    protocol => PF_INET,
    flags    => 0,
});

See UniEvent::Resolver for more info.

ssl_ctx([$ssl_ctx])

Get/set ssl context. By default, ssl context is autocreated when HTTPS location is requested, but for more precise control (validating server's certificate, authorizing via ssl, etc) ssl context can be created by hand via Net::SSLeay module and passed here.

After creating context via Net::SSLeay and passing to this method, you can release context via CTX_free() function from Net::SSLeay as it is refcounted and held by request object.

my $ctx = Net::SSLeay::CTX_new();
Net::SSLeay::CTX_use_certificate_file($ctx, "cert/ca.pem", Net::SSLeay::FILETYPE_PEM);
Net::SSLeay::CTX_use_PrivateKey_file($ctx, "cert/ca.key", Net::SSLeay::FILETYPE_PEM);
Net::SSLeay::CTX_check_private_key($ctx) or die "wtf?";

$request->ssl_ctx($ctx);

Net::SSLeay::CTX_free($ctx);

proxy([$url])

Get/set socks5 proxy url as string or URI::XS object. Url scheme must be socks5.

$request->proxy("socks5://proxy.com:1234");
$request->proxy("socks5://login:pass@proxy.com:1234");

response_callback($sub)

response_event()

Callbacks set via these methods will be invoked when response is fully received including all body or if an error occurs.

Callback signature:

my ($request, $response, $error) = @_;

Where $request is the original request object being executed.

$response is a UniEvent::HTTP::Response object containing all http response properties.

$error is an optional XS::ErrorCode object and if it is present then $response may be undefined. If the error occured while receiving response, then $response will present and contain everything parsed till that moment. $error can be one of listed in UniEvent::HTTP::Error, Protocol::HTTP::Error or UniEvent::SystemError and it can be nested, see XS::ErrorCode.

See "EVENT CALLBACKS" in UniEvent for differences between _callback and _event versions of methods.

partial_callback($sub)

partial_event()

Invoked one or more times, every time data arrives from network.

Callback signature and meaning of params are the same as for response_callback:

my ($request, $response, $error) = @_;

First time it is called when all headers arrived. From call to call response's body will grow until it's done or error occurs. If $response->is_done() is true or $error is set, then it's the last call.

The actual body part arrived is the difference between current body value and previous body value. If you only need that part, not the whole growing body (for writing to disk / incremental parsing / saving memory) then just clear the body on each call (because new parts just append to current $response->body value).

$request->partial_callback(sub {
    my ($req, $res, $error) = @_;
    if ($error) {
        ...
        return;
    }
    
    print $fh $res->body; # or asynchronously
    $res->body("");
    
    if ($res->is_done) {
        close $fh;
        ...
    }
})

If response_callback is set, it will also be called after the last call to partial_callback. The response body in response_callback will not be the full response body if you cleared it in partial_callback.

See "EVENT CALLBACKS" in UniEvent for differences between _callback and _event versions of methods.

redirect_callback($sub)

redirect_event()

Invoked right before redirection response will be followed (if follow_redirect is true).

This callback gives user a control over redirection process.

Callback signature:

my ($request, $response, $redirect_context) = @_;

Where $request is the original request object with some properties modified (uri, headers, ssl_ctx).

$response is the current redirection response.

$redirect_context is an UniEvent::HTTP::RedirectContext object which stores some of original properties of request which got replaced with new ones.

When this callback is called, $request has already been modified for new http request which will be made after this callback returns. Request uri is changed to point to the new location, headers Authorization, Cookie, Referer are removed for security reasons and ssl_ctx is cleared also if any. No heuristics are made in order to determine if new location is the same server or not, to keep those properties intact. You are free to change any request properties here (restore those headers back again or set ssl_ctx or whatsoever) and they will be used. If you want to access original values of those properties, they are stored in $redirect_context - see UniEvent::HTTP::RedirectContext.

You are also free to cancel() request here if needed.

See "EVENT CALLBACKS" in UniEvent for differences between _callback and _event versions of methods.

continue_callback($sub)

continue_event()

Invoked when server sends 100 continue intermediate message.

Normally, server can only send 100 continue if client agrees to receive such messages via setting Expect: 100-continue header. So you will also need to set

$request->header("Expect", "100-continue")

To use this callback.

Callback signature:

my $request = shift; # the request object itself

See "EVENT CALLBACKS" in UniEvent for differences between _callback and _event versions of methods.

cancel([$error = UniEvent::SystemError::operation_canceled])

Cancels request if it's active. All network activity gets stopped and response_callback and partial_callback are called with $error which is UniEvent::SystemError::operation_canceled by default.

If request is not active (finished or not yet started) does nothing.

transfer_completed()

Returns true if request has been fully send to network including all the body. For example, if you make a chunked request, it will return false from this method until you finish the sequence send_chunk(), send_chunk(), ..., send_final_chunk().

send_chunk($data)

Should only be called on requests where chunked is true. Sends an http chunk (applying possible compression, etc).

send_final_chunk([$data])

Should only be called on requests where chunked is true. Sends final (empty) http chunk and finishes sending chunked http request. If optional $data is provided, then sends $data as normal chunk before final chunk.

response_factory([$sub])

Get/set response factory subroutine. Allows for customization of response object. If factory is set, it will be called (once per http request) and its result will be used as response object. It can be of any class but it must inherit UniEvent::HTTP::Response and it must proxy to original new() method of UniEvent::HTTP::Response if you override it, see UniEvent::HTTP::Response.

Factory subroutine receives single argument - the request object and is expected to return single value - the response object.

$request->response_factory(sub {
    my $request = shift;
    my $response = MyResponse->new;
    ...
    return $response;
});