Catalyst-Engine-HTTP-Prefork

 view release on metacpan or  search on metacpan

MANIFEST  view on Meta::CPAN

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

README  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.

  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 2.071 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )