AnyEvent-HTTPD
view release on metacpan or search on metacpan
lib/AnyEvent/HTTPD/HTTPConnection.pm view on Meta::CPAN
my $hdr;
$header =~ y/\015//d;
while ($header =~ /\G
([^:\000-\037]+):
[\011\040]*
( (?: [^\012]+ | \012 [\011\040] )* )
\012
/sgcxo) {
$hdr->{lc $1} .= ",$2"
}
return undef unless $header =~ /\G$/sgxo;
for (keys %$hdr) {
substr $hdr->{$_}, 0, 1, '';
# remove folding:
$hdr->{$_} =~ s/\012([\011\040])/$1/sgo;
}
$hdr
}
sub push_header {
my ($self, $hdl) = @_;
$self->{hdl}->unshift_read (line =>
qr{(?<![^\012])\015?\012}o,
sub {
my ($hdl, $data) = @_;
my $hdr = _parse_headers ($data);
unless (defined $hdr) {
$self->error (599 => "garbled headers");
}
push @{$self->{last_header}}, $hdr;
if (defined $hdr->{'content-length'}) {
$self->{hdl}->unshift_read (chunk => $hdr->{'content-length'}, sub {
my ($hdl, $data) = @_;
$self->handle_request (@{$self->{last_header}}, $data);
});
} else {
$self->handle_request (@{$self->{last_header}});
}
}
);
}
sub push_header_line {
my ($self) = @_;
return if $self->{disconnected};
weaken $self;
$self->{req_timeout} =
AnyEvent->timer (after => $self->{request_timeout}, cb => sub {
return unless defined $self;
$self->do_disconnect ("request timeout ($self->{request_timeout})");
});
$self->{hdl}->push_read (line => sub {
my ($hdl, $line) = @_;
return unless defined $self;
delete $self->{req_timeout};
if ($line =~ /(\S+) \040 (\S+) \040 HTTP\/(\d+)\.(\d+)/xso) {
my ($meth, $url, $vm, $vi) = ($1, $2, $3, $4);
if (not grep { $meth eq $_ } @{ $self->{allowed_methods} }) {
$self->error (501, "not implemented",
{ Allow => join(",", @{ $self->{allowed_methods} })});
return;
}
if ($vm >= 2) {
$self->error (506, "http protocol version not supported");
return;
}
$self->{last_header} = [$meth, $url];
$self->push_header;
} elsif ($line eq '') {
# ignore empty lines before requests, this prevents
# browser bugs w.r.t. keep-alive (according to marc lehmann).
$self->push_header_line;
} else {
$self->error (400 => 'bad request');
}
});
}
sub do_disconnect {
my ($self, $err) = @_;
return if $self->{disconnected};
$self->{disconnected} = 1;
$self->{transfer_cb}->() if $self->{transfer_cb};
delete $self->{transfer_cb};
delete $self->{req_timeout};
$self->event ('disconnect', $err);
shutdown $self->{hdl}->{fh}, 1;
$self->{hdl}->on_read (sub { });
$self->{hdl}->on_eof (undef);
my $timer;
$timer = AE::timer 2, 0, sub {
undef $timer;
delete $self->{hdl};
};
}
1;
( run in 0.589 second using v1.01-cache-2.11-cpan-02777c243ea )