File Coverage

blib/lib/Plack/HTTPParser/PP.pm
Criterion Covered Total %
statement 53 55 96.3
branch 13 20 65.0
condition 6 10 60.0
subroutine 5 5 100.0
pod 0 1 0.0
total 77 91 84.6


line stmt bran cond sub pod time code
1             package Plack::HTTPParser::PP;
2 40     40   54723 use strict;
  40         60  
  40         1782  
3 40     40   198 use warnings;
  40         116  
  40         1661  
4 40     40   1298 use URI::Escape;
  40         5186  
  40         34991  
5              
6             sub parse_http_request {
7 710     710 0 3785 my($chunk, $env) = @_;
8 710   50     1746 $env ||= {};
9              
10             # pre-header blank lines are allowed (RFC 2616 4.1)
11 710         10421 $chunk =~ s/^(\x0d?\x0a)+//;
12 710 50       2556 return -2 unless length $chunk;
13              
14             # double line break indicates end of header; parse it
15 710 50       8566 if ($chunk =~ /^(.*?\x0d?\x0a\x0d?\x0a)/s) {
16 710         7273 return _parse_header($chunk, length $1, $env);
17             }
18 0         0 return -2; # still waiting for unknown amount of header lines
19             }
20              
21             sub _parse_header {
22 710     710   3330 my($chunk, $eoh, $env) = @_;
23              
24 710         3329 my $header = substr($chunk, 0, $eoh,'');
25 710         1439 $chunk =~ s/^\x0d?\x0a\x0d?\x0a//;
26              
27             # parse into lines
28 710         10368 my @header = split /\x0d?\x0a/,$header;
29 710         2853 my $request = shift @header;
30              
31             # join folded lines
32 710         1000 my @out;
33 710         2335 for(@header) {
34 2452 100       5229 if(/^[ \t]+/) {
35 2 50       4 return -1 unless @out;
36 2         4 $out[-1] .= $_;
37             } else {
38 2450         4911 push @out, $_;
39             }
40             }
41              
42             # parse request or response line
43 710         1717 my $obj;
44 710         1832 my ($major, $minor);
45              
46 710         3661 my ($method,$uri,$http) = split / /,$request;
47 710 50 33     9658 return -1 unless $http and $http =~ /^HTTP\/(\d+)\.(\d+)$/i;
48 710         9090 ($major, $minor) = ($1, $2);
49              
50 710         3333 $env->{REQUEST_METHOD} = $method;
51 710         2891 $env->{SERVER_PROTOCOL} = "HTTP/$major.$minor";
52 710         1448 $env->{REQUEST_URI} = $uri;
53              
54 710         9430 my($path, $query) = ( $uri =~ /^([^?]*)(?:\?(.*))?$/s );
55 710 100 66     2681 for ($path, $query) { s/\#.*$// if defined && length } # dumb clients sending URI fragments
  1420         8614  
56              
57 710         11978 $env->{PATH_INFO} = URI::Escape::uri_unescape($path);
58 710   100     16668 $env->{QUERY_STRING} = $query || '';
59 710         1869 $env->{SCRIPT_NAME} = '';
60              
61             # import headers
62 710         7993 my $token = qr/[^][\x00-\x1f\x7f()<>@,;:\\"\/?={} \t]+/;
63 710         1874 my $k;
64 710         2801 for my $header (@out) {
65 2450 50       21522 if ( $header =~ s/^($token): ?// ) {
    0          
66 2450         6808 $k = $1;
67 2450         10631 $k =~ s/-/_/g;
68 2450         5517 $k = uc $k;
69              
70 2450 100       5969 if ($k !~ /^(?:CONTENT_LENGTH|CONTENT_TYPE)$/) {
71 2234         4583 $k = "HTTP_$k";
72             }
73             } elsif ( $header =~ /^\s+/) {
74             # multiline header
75             } else {
76 0         0 return -1;
77             }
78              
79 2450 100       6126 if (exists $env->{$k}) {
80 19         310 $env->{$k} .= ", $header";
81             } else {
82 2431         9044 $env->{$k} = $header;
83             }
84             }
85              
86 710         4397 return $eoh;
87             }
88              
89             1;
90              
91             __END__