Catalyst-Engine-HTTP-Prefork
view release on metacpan or search on metacpan
t/live_engine_response_redirect.t
t/live_engine_response_status.t
t/live_engine_setup_basics.t
t/live_engine_setup_plugins.t
t/live_fork.t
t/live_http11_request_absolute.t
t/live_http11_request_chunked.t
t/live_http11_request_pipelined.t
t/live_http11_response_100continue.t
t/live_http11_response_chunked.t
t/live_http11_response_keepalive.t
t/live_loop.t
t/live_plugin_loaded.t
t/live_priorities.t
t/live_recursion.t
t/live_stats.t
t/optional_prefork-server.t
t/testapp_prefork.pl
By setting the Transfer-Encoding header to 'chunked', you can indicate
you would like the response to be sent to the client as a chunked
response. Also, any responses without a content-length will be sent
chunked.
Pipelined Requests
Browsers sending any number of pipelined requests will be handled
properly.
Keep-Alive
Keep-alive is supported for both HTTP/1.1 (by default) and HTTP/1.0 (if
a Connection: keep-alive header is present in the request).
CUSTOMIZATION
Additional options may be passed to the engine by modifying
yourapp_server.pl to send additional items to the run() method.
min_servers
The minimum number of servers to keep running. Defaults to 5.
min_spare_servers
The minimum number of servers to have waiting for requests. Minimum and
lib/Catalyst/Engine/HTTP/Prefork.pm view on Meta::CPAN
}
# The below methods run in the child process
sub post_accept_hook {
my $self = shift;
$self->{client} = {
headerbuf => '',
inputbuf => '',
keepalive => 1,
};
}
sub process_request {
my $self = shift;
my $conn = $self->{server}->{client};
while ( $self->{client}->{keepalive} ) {
last if !$conn->connected;
# Read until we see all headers
last if !$self->_read_headers;
# Parse headers
my $h = HTTP::HeaderParser::XS->new( \delete $self->{client}->{headerbuf} );
if ( !$h ) {
# Bad request
lib/Catalyst/Engine/HTTP/Prefork.pm view on Meta::CPAN
# prepare_connection and prepare_path need a few headers in %ENV
$ENV{HTTP_X_FORWARDED_FOR} = $headers->{'X-Forwarded-For'}
if $headers->{'X-Forwarded-For'};
$ENV{HTTP_X_FORWARDED_HOST} = $headers->{'X-Forwarded-Host'}
if $headers->{'X-Forwarded-Host'};
# Determine whether we will keep the connection open after the request
my $connection = $headers->{Connection};
if ( $proto && $proto eq 'HTTP/1.0' ) {
if ( $connection && $connection =~ /^keep-alive$/i ) {
# Keep-alive only with explicit header in HTTP/1.0
$self->{client}->{keepalive} = 1;
}
else {
$self->{client}->{keepalive} = 0;
}
}
elsif ( $proto && $proto eq 'HTTP/1.1' ) {
if ( $connection && $connection =~ /^close$/i ) {
$self->{client}->{keepalive} = 0;
}
else {
# Keep-alive assumed in HTTP/1.1
$self->{client}->{keepalive} = 1;
}
# Do we need to send 100 Continue?
if ( $headers->{Expect} ) {
if ( $headers->{Expect} eq '100-continue' ) {
syswrite STDOUT, 'HTTP/1.1 100 Continue' . $CRLF . $CRLF;
DEBUG && warn "[$$] Sent 100 Continue response\n";
}
else {
DEBUG && warn "[$$] Invalid Expect header, returning 417\n";
lib/Catalyst/Engine/HTTP/Prefork.pm view on Meta::CPAN
$self->_http_error( 400, 'HTTP/1.1' );
last;
}
}
# Pass flow control to Catalyst
$self->{appclass}->handle_request( $self->{client} );
DEBUG && warn "[$$] Request done\n";
if ( $self->{client}->{keepalive} ) {
# If we still have data in the input buffer it may be a pipelined request
if ( $self->{client}->{inputbuf} ) {
if ( $self->{client}->{inputbuf} =~ /^(?:GET|HEAD)/ ) {
if ( DEBUG ) {
warn "Pipelined GET/HEAD request in input buffer: "
. dump( $self->{client}->{inputbuf} ) . "\n";
}
# Continue processing the input buffer
next;
lib/Catalyst/Engine/HTTP/Prefork.pm view on Meta::CPAN
# Input buffer just has junk, clear it
if ( DEBUG ) {
warn "Clearing junk from input buffer: "
. dump( $self->{client}->{inputbuf} ) . "\n";
}
$self->{client}->{inputbuf} = '';
}
}
DEBUG && warn "[$$] Waiting on previous connection for keep-alive request...\n";
my $sel = IO::Select->new($conn);
last unless $sel->can_read(1);
}
}
DEBUG && warn "[$$] Closing connection\n";
}
sub _read_headers {
lib/Catalyst/Engine/HTTP/Prefork.pm view on Meta::CPAN
By setting the Transfer-Encoding header to 'chunked', you can indicate you
would like the response to be sent to the client as a chunked response. Also,
any responses without a content-length will be sent chunked.
=head2 Pipelined Requests
Browsers sending any number of pipelined requests will be handled properly.
=head2 Keep-Alive
Keep-alive is supported for both HTTP/1.1 (by default) and HTTP/1.0 (if a
Connection: keep-alive header is present in the request).
=head1 CUSTOMIZATION
Additional options may be passed to the engine by modifying
yourapp_server.pl to send additional items to the run() method.
=head2 min_servers
The minimum number of servers to keep running. Defaults to 5.
lib/Catalyst/Engine/HTTP/Prefork/Handler.pm view on Meta::CPAN
}
}
if ( !$c->response->header('Date') ) {
$c->response->header( Date => time2str( time() ) );
}
$c->response->header( Status => $c->response->status );
# Should we keep the connection open?
if ( $self->{client}->{keepalive} ) {
$c->response->headers->header( Connection => 'keep-alive' );
}
else {
$c->response->headers->header( Connection => 'close' );
}
push @headers, $c->response->headers->as_string($CRLF);
# Buffer the headers so they are sent with the first write() call
# This reduces the number of TCP packets we are sending
$self->{_header_buf} = join( $CRLF, @headers, '' );
t/live_http11_request_pipelined.t view on Meta::CPAN
my $server = URI->new( $ENV{CATALYST_SERVER} || 'http://localhost' );
my $base = $server->host . ':' . $server->port;
my @reqs = (
"http://$base/dump/request?req=1",
"http://$base/dump/request?req=2",
"http://$base/dump/request?req=3",
"http://$base/dump/request?req=4",
);
# Make first request normally, we then reuse the keep-alive connection
# to pipeline the next 3 requests
my $sock = IO::Socket::INET->new(
PeerAddr => $server->host,
PeerPort => $server->port,
Proto => 'tcp',
ReuseAddr => 1,
Timeout => 2,
) or die "Cannot connect to $server";
# Send request
syswrite $sock, construct_request( shift @reqs );
# Read/parse response
sysread $sock, my $buf, 64 * 1024;
my $response = HTTP::Response->parse($buf);
is( $response->code, 200, 'Response ok' );
is( $response->header('Connection'), 'keep-alive', 'Keep-alive header ok' );
my $creq;
ok( eval '$creq = ' . $response->content, 'Unserialize Catalyst::Request' );
is( $creq->{parameters}->{req}, 1, 'request 1 ok' );
# Send next 3 requests pipelined
syswrite $sock, construct_request( @reqs );
# Read all responses into one big buffer
my $pipebuf;
t/live_http11_response_keepalive.t view on Meta::CPAN
use IO::Socket::INET;
use HTTP::Response;
use URI;
# With LWP it is difficult or impossible to change the Connection header
# or use HTTP/1.0, so manually create some requests
my $server = URI->new( $ENV{CATALYST_SERVER} || 'http://localhost' );
my $base = $server->host . ':' . $server->port;
# Test normal HTTP/1.1 request, should return Connection: keep-alive
{
my $sock = IO::Socket::INET->new(
PeerAddr => $server->host,
PeerPort => $server->port,
Proto => 'tcp',
ReuseAddr => 1,
Timeout => 2,
) or die "Cannot connect to $server";
# Send request
syswrite $sock, construct_request( "http://$base/dump/request", '1.1', 'keep-alive' );
# Read/parse response
sysread $sock, my $buf, 64 * 1024;
my $response = HTTP::Response->parse($buf);
is( $response->header('Connection'), 'keep-alive', 'HTTP/1.1, keep-alive ok' );
}
# Test HTTP/1.1 with Connection: close, should return Connection: close
{
my $sock = IO::Socket::INET->new(
PeerAddr => $server->host,
PeerPort => $server->port,
Proto => 'tcp',
ReuseAddr => 1,
Timeout => 2,
t/live_http11_response_keepalive.t view on Meta::CPAN
# Send request
syswrite $sock, construct_request( "http://$base/dump/request", '1.1', 'close' );
# Read/parse response
sysread $sock, my $buf, 64 * 1024;
my $response = HTTP::Response->parse($buf);
is( $response->header('Connection'), 'close', 'HTTP/1.1, close ok' );
}
# Test HTTP/1.0 with Connection: Keep-Alive header, should return Connection: keep-alive
{
my $sock = IO::Socket::INET->new(
PeerAddr => $server->host,
PeerPort => $server->port,
Proto => 'tcp',
ReuseAddr => 1,
Timeout => 2,
) or die "Cannot connect to $server";
# Send request
syswrite $sock, construct_request( "http://$base/dump/request", '1.0', 'keep-alive' );
# Read/parse response
sysread $sock, my $buf, 64 * 1024;
my $response = HTTP::Response->parse($buf);
is( $response->header('Connection'), 'keep-alive', 'HTTP/1.0, keep-alive ok' );
}
# Test HTTP/1.0 with no Connection header, should return Connection: close
{
my $sock = IO::Socket::INET->new(
PeerAddr => $server->host,
PeerPort => $server->port,
Proto => 'tcp',
ReuseAddr => 1,
Timeout => 2,
( run in 4.347 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )