Arriba
view release on metacpan or search on metacpan
lib/Arriba/Connection/HTTP.pm view on Meta::CPAN
package Arriba::Connection::HTTP;
use warnings;
use strict;
use Data::Dump qw(dump);
use HTTP::Status qw(status_message);
use IO::Socket qw(:crlf);
use Plack::Util;
use Socket qw(IPPROTO_TCP TCP_NODELAY);
use base 'Arriba::Connection';
sub new {
my $class = shift;
my $self = $class->SUPER::new(@_);
if ($self->{client}->NS_proto eq 'TCP') {
setsockopt($self->{client}, IPPROTO_TCP, TCP_NODELAY, 1)
or die $!;
}
$self->{_inputbuf} = '';
$self->{_current_req} = undef;
$self->{_keepalive} = 1;
return $self;
}
sub read_request {
my $self = shift;
my $req;
if ($req = $self->{_current_req}) {
# Partially processed request
my $get_chunk = sub {
if ($self->{_inputbuf}) {
my $chunk = delete $self->{_inputbuf};
return ($chunk, length $chunk);
}
my $read = sysread $self->{client}, my($chunk), $self->{chunk_size};
return ($chunk, $read);
};
my $chunked = do {
no warnings;
lc delete $req->{env}->{HTTP_TRANSFER_ENCODING} eq 'chunked'
};
if ((my $cl = $req->{content_length}) >= 0) {
$req->{body_stream} = Stream::Buffered->new($req->{content_length});
while ($cl > 0) {
my($chunk, $read) = $get_chunk->();
if (!defined $read || $read == 0) {
die "Read error: $!\n";
}
$cl -= $read;
$req->{body_stream}->print($chunk);
}
}
elsif ($chunked) {
$req->{body_stream} = Stream::Buffered->new;
my $chunk_buffer = '';
my $length;
DECHUNK:
while (1) {
my($chunk, $read) = $get_chunk->();
$chunk_buffer .= $chunk;
while ($chunk_buffer =~ s/^(([0-9a-fA-F]+).*\015\012)// ) {
my $trailer = $1;
my $chunk_len = hex $2;
( run in 0.892 second using v1.01-cache-2.11-cpan-8f98c5d2c55 )