NAME
UniEvent::HTTP::ServerRequest - HTTP server request class
SYNOPSIS
# simple
$server->request_callback(sub {
my $request = shift;
say $request->method_str;
say $request->uri;
say $request->body;
say Dumper($request->headers);
$request->respond({
code => 200,
body => "hello",
});
});
#request body streaming
$server->route_callback(sub {
my $request = shift;
if ($request->uri == "/upload_data") {
# open $fh
$request->enable_partial;
$request->partial_callback(sub {
my ($request, $error) = @_;
if ($error) {
log("something went wrong: $error");
# delete file
}
# write $request->body to $fh
$request->body("");
if ($request->is_done) {
# close $fh
$request->respond({
code => 200,
body => "uploaded!",
});
}
});
}
});
# tracking if response no longer needed
$server->request_callback(sub {
my $request = shift;
start_hard_work_calculating_response_data($request, sub {
my $request = shift;
$request->respond({
code => 200,
body => $data,
});
});
$request->drop_event(sub {
my ($request, $error) = @_;
log("request has been canceled because: $error");
cancel_hard_work_for($request);
});
});
DESCRIPTION
UniEvent::HTTP::ServerRequest
is used to represent client's request on server. It holds all the properties and state of http request. It is passed to various callbacks listening for request receiving events in server.
ServerRequest has API to control how certain request will be received and API for responding on request.
UniEvent::HTTP::ServerRequest
inherits from Protocol::HTTP::Request. So for complete documenation you need to also read Protocol::HTTP::Request's docs.
METHODS
All methods of Protocol::HTTP::Request also apply.
receive_callback($sub)
receive_event()
Callbacks set via these methods will be invoked when request is fully received including all body. Use this event when you decide to fully receive the request in memory and process request when it's fully available.
Callback signature:
my $request = shift; # request object itself
Setting callbacks for this event is only meaningful in server's route_callback
/route_event
as it is the only place where you can access not yet received request object.
See "EVENT CALLBACKS" in UniEvent for differences between _callback
and _event
versions of methods.
partial_callback($sub)
partial_event()
Callbacks set via these methods will be invoked one or more times as data (body) arrives from network for the request. Partial receival mode must be enabled via enable_partial()
, otherwise no callbacks will be called. Use this event if you decide to process body on-the-fly by parts as they arrives from nertwork. For example, to incremental parse content or to write body to disk without consuming memory.
Callback signature:
my ($request, $error) = @_;
Where $request
is the request object itself. From call to call request's body will grow until it's done or error occurs. If $request->is_done() is true or $error
is set, then it's the last call.
See UniEvent::HTTP::Request's partial_callback
description for details as behaviour is the same.
$server->route_callback(sub {
my $request = shift;
if ($request->uri == "/upload_data") {
# open $fh
$request->enable_partial;
$request->partial_callback(sub {
my ($request, $error) = @_;
if ($error) {
log("something went wrong: $error");
# delete file
}
# write $request->body to $fh
$request->body("");
if ($request->is_done) {
# close $fh
$request->respond({
code => 200,
body => "uploaded!",
});
}
});
}
});
Setting callbacks for this event is only meaningful in server's route_callback
/route_event
as it is the only place where you can access not yet received request object.
See "EVENT CALLBACKS" in UniEvent for differences between _callback
and _event
versions of methods.
drop_callback($sub)
drop_event()
Callbacks set via these methods will be invoked when response for the fully received request is no longer needed. The reasons why it's not needed anymore may be: connection loss, I/O errors, manual dropping request, timeout, etc...
Callback signature:
my ($request, $error) = @_;
Where $request
is the request object itself. $error
is a XS::ErrorCode object which explains why the response is no longer needed.
IMPORTANT: for requests that are not yet fully received (not is_done()
), these callbacks will not be called, because in this case other error-reporting method is used. For partial-mode requests, partial callbacks will be called with error. For non-partial-mode requests no actions required because user doesn't know yet about such requests as callbacks like receive_callback
or request_callback
in server are only invoked when request is fully received. Such scenarios are reported into general error callbacks in server: error_callback
.
The main goal of this event is to allow user to cancel some hard work he started to generate response for the request when the response is no longer needed. For conveniency, UniEvent::HTTP
doesn't require a user to check if connection is still alive or check for I/O errors, thus it just silently ignores all data that user sends in this case. So that this event is solely a matter of optimisation, it just signals user that no one is waiting for the results anymore.
$server->request_callback(sub {
my $request = shift;
start_hard_work_calculating_response_data($request, sub {
my $request = shift;
$request->respond({
code => 200,
body => $data,
});
});
$request->drop_event(sub {
my ($request, $error) = @_;
log("request has been canceled because: $error");
cancel_hard_work_for($request);
});
});
See "EVENT CALLBACKS" in UniEvent for differences between _callback
and _event
versions of methods.
finish_callback($sub)
finish_event()
Callbacks set via these methods will be invoked when http request cycle is finished, i.e. when response for the request is fully given and sent to network and server is about to forget this request and its response.
Callback signature:
my $request = shift; # request object itself
enable_partial()
Enables partial receival mode for the request. Enabling this mode is only meaningful in server's route_callback
/route_event
as it is the only place where you can access not yet received request object.
is_done()
Returns true if request has been fully received (including body). Useful in partial mode callbacks.
is_secure()
Returns true if the request is made using SSL (HTTPS).
if ($request->uri == "/admin" && !$request->is_secure) {
$request->redirect("https://mysite.com/admin");
return;
}
sockaddr()
Returns address of the location which client is connected to. I.e. it is one of the $server->listeners address. If you have only one listener, then the returned address will be equal to $server->sockaddr. Address returned as Net::SockAddr object.
peeraddr()
Returns client's address as Net::SockAddr object. May return undef
if connection is no longer alive or request-response cycle has been finished.
if ($request->uri == "/admin" && $request->peeraddr->ip ne '1.1.1.1') {
$request->respond({code => 403});
return;
}
respond($response || \%response_params)
Send response for the request. Argument can be a UniEvent::HTTP::ServerResponse object or params to its constructor. If response is not complete (for example chunked response started) then further activity on response object is required.
$request->respond({
code => 200,
body => "hi",
headers => {Foo => "bar"},
});
my $response = UE::HTTP::ServerResponse->new({code => 404});
$request->respond($response);
$request->respond({
code => 200,
chunked => 1,
});
...
# later
$request->response->send_chunk($data1);
...
$request->response->send_chunk($dataN);
$request->response->send_final_chunk;
Does nothing if request has been dropped.
response()
Returns response object (UniEvent::HTTP::ServerResponse) associated with the request. Will return undef
if respond()
has not been called yet. Useful for responses which is sent by parts (chunked) and thus further response object iteraction is required.
redirect($uri)
Sends redirection response. $uri
may be a string or anything that stringifies.
The same as
$request->respond({
code => 302,
headers => {Location => "$uri"},
});
send_continue()
Sends 100-continue
intermediate response to client during request receival.
Does nothing if request is HTTP/1.0 or client didn't ask for that (no Expect: 100-continue
header).
Will throw if response for the request has already been sent or started.
drop()
Drop the request and make response no longer needed. Underlying connection will be closed and drop_callback/event
will be called with error UniEvent::SystemError::operation_canceled
.