| Filename | /usr/local/share/perl/5.18.2/Plack/Request.pm |
| Statements | Executed 8909665 statements in 37.5s |
| Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
|---|---|---|---|---|---|
| 200002 | 2 | 1 | 17.6s | 37.1s | Plack::Request::headers |
| 100001 | 1 | 1 | 5.31s | 12.3s | Plack::Request::_parse_query |
| 599517 | 4 | 1 | 3.54s | 4.53s | Plack::Request::method |
| 3002136 | 2 | 1 | 1.71s | 1.71s | Plack::Request::CORE:match (opcode) |
| 1299524 | 7 | 1 | 1.58s | 1.58s | Plack::Request::env |
| 200002 | 2 | 1 | 1.31s | 1.52s | Plack::Request::content_length |
| 100001 | 1 | 1 | 1.21s | 13.5s | Plack::Request::query_parameters |
| 904221 | 3 | 1 | 1.18s | 1.18s | Plack::Request::CORE:subst (opcode) |
| 100001 | 1 | 1 | 788ms | 788ms | Plack::Request::new |
| 100001 | 1 | 1 | 671ms | 735ms | Plack::Request::request_uri |
| 100001 | 1 | 1 | 652ms | 719ms | Plack::Request::path_info |
| 1 | 1 | 1 | 5.69ms | 5.86ms | Plack::Request::BEGIN@7 |
| 1 | 1 | 1 | 3.90ms | 21.3ms | Plack::Request::BEGIN@10 |
| 1 | 1 | 1 | 2.44ms | 2.72ms | Plack::Request::BEGIN@9 |
| 1 | 1 | 1 | 304µs | 341µs | Plack::Request::BEGIN@12 |
| 1 | 1 | 1 | 278µs | 2.30ms | Plack::Request::BEGIN@13 |
| 1 | 1 | 1 | 18µs | 46µs | Plack::Request::BEGIN@2 |
| 1 | 1 | 1 | 17µs | 17µs | Plack::Request::BEGIN@4 |
| 1 | 1 | 1 | 17µs | 27µs | Plack::Request::BEGIN@3 |
| 1 | 1 | 1 | 8µs | 8µs | Plack::Request::BEGIN@8 |
| 1 | 1 | 1 | 7µs | 7µs | Plack::Request::BEGIN@14 |
| 1 | 1 | 1 | 2µs | 2µs | Plack::Request::BEGIN@15 |
| 0 | 0 | 0 | 0s | 0s | Plack::Request::_make_upload |
| 0 | 0 | 0 | 0s | 0s | Plack::Request::_parse_request_body |
| 0 | 0 | 0 | 0s | 0s | Plack::Request::_uri_base |
| 0 | 0 | 0 | 0s | 0s | Plack::Request::address |
| 0 | 0 | 0 | 0s | 0s | Plack::Request::base |
| 0 | 0 | 0 | 0s | 0s | Plack::Request::body |
| 0 | 0 | 0 | 0s | 0s | Plack::Request::body_parameters |
| 0 | 0 | 0 | 0s | 0s | Plack::Request::content |
| 0 | 0 | 0 | 0s | 0s | Plack::Request::content_encoding |
| 0 | 0 | 0 | 0s | 0s | Plack::Request::content_type |
| 0 | 0 | 0 | 0s | 0s | Plack::Request::cookies |
| 0 | 0 | 0 | 0s | 0s | Plack::Request::header |
| 0 | 0 | 0 | 0s | 0s | Plack::Request::input |
| 0 | 0 | 0 | 0s | 0s | Plack::Request::logger |
| 0 | 0 | 0 | 0s | 0s | Plack::Request::new_response |
| 0 | 0 | 0 | 0s | 0s | Plack::Request::param |
| 0 | 0 | 0 | 0s | 0s | Plack::Request::parameters |
| 0 | 0 | 0 | 0s | 0s | Plack::Request::path |
| 0 | 0 | 0 | 0s | 0s | Plack::Request::port |
| 0 | 0 | 0 | 0s | 0s | Plack::Request::protocol |
| 0 | 0 | 0 | 0s | 0s | Plack::Request::query_string |
| 0 | 0 | 0 | 0s | 0s | Plack::Request::raw_body |
| 0 | 0 | 0 | 0s | 0s | Plack::Request::referer |
| 0 | 0 | 0 | 0s | 0s | Plack::Request::remote_host |
| 0 | 0 | 0 | 0s | 0s | Plack::Request::scheme |
| 0 | 0 | 0 | 0s | 0s | Plack::Request::script_name |
| 0 | 0 | 0 | 0s | 0s | Plack::Request::secure |
| 0 | 0 | 0 | 0s | 0s | Plack::Request::session |
| 0 | 0 | 0 | 0s | 0s | Plack::Request::session_options |
| 0 | 0 | 0 | 0s | 0s | Plack::Request::upload |
| 0 | 0 | 0 | 0s | 0s | Plack::Request::uploads |
| 0 | 0 | 0 | 0s | 0s | Plack::Request::uri |
| 0 | 0 | 0 | 0s | 0s | Plack::Request::user |
| 0 | 0 | 0 | 0s | 0s | Plack::Request::user_agent |
| Line | State ments |
Time on line |
Calls | Time in subs |
Code |
|---|---|---|---|---|---|
| 1 | package Plack::Request; | ||||
| 2 | 2 | 42µs | 2 | 75µs | # spent 46µs (18+28) within Plack::Request::BEGIN@2 which was called:
# once (18µs+28µs) by PONAPI::CLI::RunServer::BEGIN@4.20 at line 2 # spent 46µs making 1 call to Plack::Request::BEGIN@2
# spent 28µs making 1 call to strict::import |
| 3 | 2 | 38µs | 2 | 37µs | # spent 27µs (17+10) within Plack::Request::BEGIN@3 which was called:
# once (17µs+10µs) by PONAPI::CLI::RunServer::BEGIN@4.20 at line 3 # spent 27µs making 1 call to Plack::Request::BEGIN@3
# spent 10µs making 1 call to warnings::import |
| 4 | 2 | 86µs | 1 | 17µs | # spent 17µs within Plack::Request::BEGIN@4 which was called:
# once (17µs+0s) by PONAPI::CLI::RunServer::BEGIN@4.20 at line 4 # spent 17µs making 1 call to Plack::Request::BEGIN@4 |
| 5 | 1 | 500ns | our $VERSION = '1.0037'; | ||
| 6 | |||||
| 7 | 2 | 175µs | 1 | 5.86ms | # spent 5.86ms (5.69+170µs) within Plack::Request::BEGIN@7 which was called:
# once (5.69ms+170µs) by PONAPI::CLI::RunServer::BEGIN@4.20 at line 7 # spent 5.86ms making 1 call to Plack::Request::BEGIN@7 |
| 8 | 2 | 33µs | 1 | 8µs | # spent 8µs within Plack::Request::BEGIN@8 which was called:
# once (8µs+0s) by PONAPI::CLI::RunServer::BEGIN@4.20 at line 8 # spent 8µs making 1 call to Plack::Request::BEGIN@8 |
| 9 | 2 | 159µs | 1 | 2.72ms | # spent 2.72ms (2.44+282µs) within Plack::Request::BEGIN@9 which was called:
# once (2.44ms+282µs) by PONAPI::CLI::RunServer::BEGIN@4.20 at line 9 # spent 2.72ms making 1 call to Plack::Request::BEGIN@9 |
| 10 | 2 | 137µs | 1 | 21.3ms | # spent 21.3ms (3.90+17.4) within Plack::Request::BEGIN@10 which was called:
# once (3.90ms+17.4ms) by PONAPI::CLI::RunServer::BEGIN@4.20 at line 10 # spent 21.3ms making 1 call to Plack::Request::BEGIN@10 |
| 11 | |||||
| 12 | 2 | 76µs | 1 | 341µs | # spent 341µs (304+36) within Plack::Request::BEGIN@12 which was called:
# once (304µs+36µs) by PONAPI::CLI::RunServer::BEGIN@4.20 at line 12 # spent 341µs making 1 call to Plack::Request::BEGIN@12 |
| 13 | 2 | 70µs | 1 | 2.30ms | # spent 2.30ms (278µs+2.02) within Plack::Request::BEGIN@13 which was called:
# once (278µs+2.02ms) by PONAPI::CLI::RunServer::BEGIN@4.20 at line 13 # spent 2.30ms making 1 call to Plack::Request::BEGIN@13 |
| 14 | 2 | 20µs | 1 | 7µs | # spent 7µs within Plack::Request::BEGIN@14 which was called:
# once (7µs+0s) by PONAPI::CLI::RunServer::BEGIN@4.20 at line 14 # spent 7µs making 1 call to Plack::Request::BEGIN@14 |
| 15 | 2 | 1.48ms | 1 | 2µs | # spent 2µs within Plack::Request::BEGIN@15 which was called:
# once (2µs+0s) by PONAPI::CLI::RunServer::BEGIN@4.20 at line 15 # spent 2µs making 1 call to Plack::Request::BEGIN@15 |
| 16 | |||||
| 17 | # spent 788ms within Plack::Request::new which was called 100001 times, avg 8µs/call:
# 100001 times (788ms+0s) by PONAPI::Server::call at line 64 of lib/PONAPI/Server.pm, avg 8µs/call | ||||
| 18 | 100001 | 84.2ms | my($class, $env) = @_; | ||
| 19 | 100001 | 152ms | Carp::croak(q{$env is required}) | ||
| 20 | unless defined $env && ref($env) eq 'HASH'; | ||||
| 21 | |||||
| 22 | 100001 | 846ms | bless { env => $env }, $class; | ||
| 23 | } | ||||
| 24 | |||||
| 25 | 1299524 | 5.11s | # spent 1.58s within Plack::Request::env which was called 1299524 times, avg 1µs/call:
# 599517 times (986ms+0s) by Plack::Request::method at line 30, avg 2µs/call
# 200002 times (213ms+0s) by Plack::Request::content_length at line 43, avg 1µs/call
# 100001 times (98.5ms+0s) by Plack::Request::headers at line 123, avg 985ns/call
# 100001 times (86.5ms+0s) by Plack::Request::query_parameters at line 80, avg 865ns/call
# 100001 times (67.5ms+0s) by Plack::Request::path_info at line 34, avg 675ns/call
# 100001 times (67.2ms+0s) by Plack::Request::_parse_query at line 87, avg 672ns/call
# 100001 times (64.9ms+0s) by Plack::Request::request_uri at line 33, avg 649ns/call | ||
| 26 | |||||
| 27 | sub address { $_[0]->env->{REMOTE_ADDR} } | ||||
| 28 | sub remote_host { $_[0]->env->{REMOTE_HOST} } | ||||
| 29 | sub protocol { $_[0]->env->{SERVER_PROTOCOL} } | ||||
| 30 | 599517 | 3.44s | 599517 | 986ms | # spent 4.53s (3.54+986ms) within Plack::Request::method which was called 599517 times, avg 8µs/call:
# 299514 times (1.30s+209ms) by PONAPI::Server::_is_get_like at line 99 of lib/PONAPI/Server.pm, avg 5µs/call
# 100001 times (869ms+332ms) by PONAPI::Server::_ponapi_check_headers at line 201 of lib/PONAPI/Server.pm, avg 12µs/call
# 100001 times (701ms+220ms) by PONAPI::Server::_ponapi_route_match at line 139 of lib/PONAPI/Server.pm, avg 9µs/call
# 100001 times (673ms+224ms) by PONAPI::Server::call at line 78 of lib/PONAPI/Server.pm, avg 9µs/call # spent 986ms making 599517 calls to Plack::Request::env, avg 2µs/call |
| 31 | sub port { $_[0]->env->{SERVER_PORT} } | ||||
| 32 | sub user { $_[0]->env->{REMOTE_USER} } | ||||
| 33 | 100001 | 531ms | 100001 | 64.9ms | # spent 735ms (671+64.9) within Plack::Request::request_uri which was called 100001 times, avg 7µs/call:
# 100001 times (671ms+64.9ms) by PONAPI::Server::_ponapi_params at line 120 of lib/PONAPI/Server.pm, avg 7µs/call # spent 64.9ms making 100001 calls to Plack::Request::env, avg 649ns/call |
| 34 | 100001 | 550ms | 100001 | 67.5ms | # spent 719ms (652+67.5) within Plack::Request::path_info which was called 100001 times, avg 7µs/call:
# 100001 times (652ms+67.5ms) by PONAPI::Server::_ponapi_route_match at line 143 of lib/PONAPI/Server.pm, avg 7µs/call # spent 67.5ms making 100001 calls to Plack::Request::env, avg 675ns/call |
| 35 | sub path { $_[0]->env->{PATH_INFO} || '/' } | ||||
| 36 | sub query_string{ $_[0]->env->{QUERY_STRING} } | ||||
| 37 | sub script_name { $_[0]->env->{SCRIPT_NAME} } | ||||
| 38 | sub scheme { $_[0]->env->{'psgi.url_scheme'} } | ||||
| 39 | sub secure { $_[0]->scheme eq 'https' } | ||||
| 40 | sub body { $_[0]->env->{'psgi.input'} } | ||||
| 41 | sub input { $_[0]->env->{'psgi.input'} } | ||||
| 42 | |||||
| 43 | 200002 | 1.27s | 200002 | 213ms | # spent 1.52s (1.31+213ms) within Plack::Request::content_length which was called 200002 times, avg 8µs/call:
# 100001 times (719ms+98.5ms) by PONAPI::Server::_ponapi_check_headers at line 208 of lib/PONAPI/Server.pm, avg 8µs/call
# 100001 times (586ms+115ms) by PONAPI::Server::_ponapi_data at line 291 of lib/PONAPI/Server.pm, avg 7µs/call # spent 213ms making 200002 calls to Plack::Request::env, avg 1µs/call |
| 44 | sub content_type { $_[0]->env->{CONTENT_TYPE} } | ||||
| 45 | |||||
| 46 | sub session { $_[0]->env->{'psgix.session'} } | ||||
| 47 | sub session_options { $_[0]->env->{'psgix.session.options'} } | ||||
| 48 | sub logger { $_[0]->env->{'psgix.logger'} } | ||||
| 49 | |||||
| 50 | sub cookies { | ||||
| 51 | my $self = shift; | ||||
| 52 | |||||
| 53 | return {} unless $self->env->{HTTP_COOKIE}; | ||||
| 54 | |||||
| 55 | # HTTP_COOKIE hasn't changed: reuse the parsed cookie | ||||
| 56 | if ( $self->env->{'plack.cookie.parsed'} | ||||
| 57 | && $self->env->{'plack.cookie.string'} eq $self->env->{HTTP_COOKIE}) { | ||||
| 58 | return $self->env->{'plack.cookie.parsed'}; | ||||
| 59 | } | ||||
| 60 | |||||
| 61 | $self->env->{'plack.cookie.string'} = $self->env->{HTTP_COOKIE}; | ||||
| 62 | |||||
| 63 | my %results; | ||||
| 64 | my @pairs = grep m/=/, split "[;,] ?", $self->env->{'plack.cookie.string'}; | ||||
| 65 | for my $pair ( @pairs ) { | ||||
| 66 | # trim leading trailing whitespace | ||||
| 67 | $pair =~ s/^\s+//; $pair =~ s/\s+$//; | ||||
| 68 | |||||
| 69 | my ($key, $value) = map URI::Escape::uri_unescape($_), split( "=", $pair, 2 ); | ||||
| 70 | |||||
| 71 | # Take the first one like CGI.pm or rack do | ||||
| 72 | $results{$key} = $value unless exists $results{$key}; | ||||
| 73 | } | ||||
| 74 | |||||
| 75 | $self->env->{'plack.cookie.parsed'} = \%results; | ||||
| 76 | } | ||||
| 77 | |||||
| 78 | # spent 13.5s (1.21+12.3) within Plack::Request::query_parameters which was called 100001 times, avg 135µs/call:
# 100001 times (1.21s+12.3s) by PONAPI::Server::_ponapi_query_params at line 240 of lib/PONAPI/Server.pm, avg 135µs/call | ||||
| 79 | 100001 | 50.0ms | my $self = shift; | ||
| 80 | 100001 | 876ms | 200002 | 12.3s | $self->env->{'plack.request.query'} ||= $self->_parse_query; # spent 12.3s making 100001 calls to Plack::Request::_parse_query, avg 123µs/call
# spent 86.5ms making 100001 calls to Plack::Request::env, avg 865ns/call |
| 81 | } | ||||
| 82 | |||||
| 83 | # spent 12.3s (5.31+6.94) within Plack::Request::_parse_query which was called 100001 times, avg 123µs/call:
# 100001 times (5.31s+6.94s) by Plack::Request::query_parameters at line 80, avg 123µs/call | ||||
| 84 | 100001 | 43.6ms | my $self = shift; | ||
| 85 | |||||
| 86 | 100001 | 32.6ms | my @query; | ||
| 87 | 100001 | 189ms | 100001 | 67.2ms | my $query_string = $self->env->{QUERY_STRING}; # spent 67.2ms making 100001 calls to Plack::Request::env, avg 672ns/call |
| 88 | 100001 | 112ms | if (defined $query_string) { | ||
| 89 | 100001 | 625ms | 100001 | 133ms | $query_string =~ s/\A[&;]+//; # spent 133ms making 100001 calls to Plack::Request::CORE:subst, avg 1µs/call |
| 90 | 204214 | 725ms | 204214 | 71.7ms | @query = # spent 71.7ms making 204214 calls to Plack::Request::CORE:subst, avg 351ns/call |
| 91 | 306321 | 982ms | 306321 | 1.40s | map { s/\+/ /g; URI::Escape::uri_unescape($_) } # spent 1.27s making 204214 calls to URI::Escape::uri_unescape, avg 6µs/call
# spent 123ms making 102107 calls to Plack::Request::CORE:match, avg 1µs/call |
| 92 | 100001 | 519ms | map { /=/ ? split(/=/, $_, 2) : ($_ => '')} | ||
| 93 | split(/[&;]+/, $query_string); | ||||
| 94 | } | ||||
| 95 | |||||
| 96 | 100001 | 1.09s | 100001 | 3.76s | Hash::MultiValue->new(@query); # spent 3.76s making 100001 calls to Hash::MultiValue::new, avg 38µs/call |
| 97 | } | ||||
| 98 | |||||
| 99 | sub content { | ||||
| 100 | my $self = shift; | ||||
| 101 | |||||
| 102 | unless ($self->env->{'psgix.input.buffered'}) { | ||||
| 103 | $self->_parse_request_body; | ||||
| 104 | } | ||||
| 105 | |||||
| 106 | my $fh = $self->input or return ''; | ||||
| 107 | my $cl = $self->env->{CONTENT_LENGTH} or return ''; | ||||
| 108 | |||||
| 109 | $fh->seek(0, 0); # just in case middleware/apps read it without seeking back | ||||
| 110 | $fh->read(my($content), $cl, 0); | ||||
| 111 | $fh->seek(0, 0); | ||||
| 112 | |||||
| 113 | return $content; | ||||
| 114 | } | ||||
| 115 | |||||
| 116 | sub raw_body { $_[0]->content } | ||||
| 117 | |||||
| 118 | # XXX you can mutate headers with ->headers but it's not written through to the env | ||||
| 119 | |||||
| 120 | # spent 37.1s (17.6+19.5) within Plack::Request::headers which was called 200002 times, avg 186µs/call:
# 100001 times (17.3s+19.5s) by PONAPI::Server::_ponapi_check_headers at line 218 of lib/PONAPI/Server.pm, avg 368µs/call
# 100001 times (280ms+0s) by PONAPI::Server::_ponapi_query_params at line 242 of lib/PONAPI/Server.pm, avg 3µs/call | ||||
| 121 | 200002 | 105ms | my $self = shift; | ||
| 122 | 200002 | 521ms | if (!defined $self->{headers}) { | ||
| 123 | 100001 | 189ms | 100001 | 98.5ms | my $env = $self->env; # spent 98.5ms making 100001 calls to Plack::Request::env, avg 985ns/call |
| 124 | 600006 | 3.52s | 600006 | 973ms | $self->{headers} = HTTP::Headers::Fast->new( # spent 973ms making 600006 calls to Plack::Request::CORE:subst, avg 2µs/call |
| 125 | map { | ||||
| 126 | 2900029 | 11.2s | 2900029 | 1.58s | (my $field = $_) =~ s/^HTTPS?_//; # spent 1.58s making 2900029 calls to Plack::Request::CORE:match, avg 546ns/call |
| 127 | 600006 | 975ms | ( $field => $env->{$_} ); | ||
| 128 | } | ||||
| 129 | 100001 | 2.86s | 100001 | 16.9s | grep { /^(?:HTTP|CONTENT)/i } keys %$env # spent 16.9s making 100001 calls to HTTP::Headers::Fast::new, avg 169µs/call |
| 130 | ); | ||||
| 131 | } | ||||
| 132 | 200002 | 930ms | $self->{headers}; | ||
| 133 | } | ||||
| 134 | |||||
| 135 | sub content_encoding { shift->headers->content_encoding(@_) } | ||||
| 136 | sub header { shift->headers->header(@_) } | ||||
| 137 | sub referer { shift->headers->referer(@_) } | ||||
| 138 | sub user_agent { shift->headers->user_agent(@_) } | ||||
| 139 | |||||
| 140 | sub body_parameters { | ||||
| 141 | my $self = shift; | ||||
| 142 | |||||
| 143 | unless ($self->env->{'plack.request.body'}) { | ||||
| 144 | $self->_parse_request_body; | ||||
| 145 | } | ||||
| 146 | |||||
| 147 | return $self->env->{'plack.request.body'}; | ||||
| 148 | } | ||||
| 149 | |||||
| 150 | # contains body + query | ||||
| 151 | sub parameters { | ||||
| 152 | my $self = shift; | ||||
| 153 | |||||
| 154 | $self->env->{'plack.request.merged'} ||= do { | ||||
| 155 | my $query = $self->query_parameters; | ||||
| 156 | my $body = $self->body_parameters; | ||||
| 157 | Hash::MultiValue->new($query->flatten, $body->flatten); | ||||
| 158 | }; | ||||
| 159 | } | ||||
| 160 | |||||
| 161 | sub uploads { | ||||
| 162 | my $self = shift; | ||||
| 163 | |||||
| 164 | if ($self->env->{'plack.request.upload'}) { | ||||
| 165 | return $self->env->{'plack.request.upload'}; | ||||
| 166 | } | ||||
| 167 | |||||
| 168 | $self->_parse_request_body; | ||||
| 169 | return $self->env->{'plack.request.upload'}; | ||||
| 170 | } | ||||
| 171 | |||||
| 172 | sub param { | ||||
| 173 | my $self = shift; | ||||
| 174 | |||||
| 175 | return keys %{ $self->parameters } if @_ == 0; | ||||
| 176 | |||||
| 177 | my $key = shift; | ||||
| 178 | return $self->parameters->{$key} unless wantarray; | ||||
| 179 | return $self->parameters->get_all($key); | ||||
| 180 | } | ||||
| 181 | |||||
| 182 | sub upload { | ||||
| 183 | my $self = shift; | ||||
| 184 | |||||
| 185 | return keys %{ $self->uploads } if @_ == 0; | ||||
| 186 | |||||
| 187 | my $key = shift; | ||||
| 188 | return $self->uploads->{$key} unless wantarray; | ||||
| 189 | return $self->uploads->get_all($key); | ||||
| 190 | } | ||||
| 191 | |||||
| 192 | sub uri { | ||||
| 193 | my $self = shift; | ||||
| 194 | |||||
| 195 | my $base = $self->_uri_base; | ||||
| 196 | |||||
| 197 | # We have to escape back PATH_INFO in case they include stuff like | ||||
| 198 | # ? or # so that the URI parser won't be tricked. However we should | ||||
| 199 | # preserve '/' since encoding them into %2f doesn't make sense. | ||||
| 200 | # This means when a request like /foo%2fbar comes in, we recognize | ||||
| 201 | # it as /foo/bar which is not ideal, but that's how the PSGI PATH_INFO | ||||
| 202 | # spec goes and we can't do anything about it. See PSGI::FAQ for details. | ||||
| 203 | |||||
| 204 | # See RFC 3986 before modifying. | ||||
| 205 | my $path_escape_class = q{^/;:@&=A-Za-z0-9\$_.+!*'(),-}; | ||||
| 206 | |||||
| 207 | my $path = URI::Escape::uri_escape($self->env->{PATH_INFO} || '', $path_escape_class); | ||||
| 208 | $path .= '?' . $self->env->{QUERY_STRING} | ||||
| 209 | if defined $self->env->{QUERY_STRING} && $self->env->{QUERY_STRING} ne ''; | ||||
| 210 | |||||
| 211 | $base =~ s!/$!! if $path =~ m!^/!; | ||||
| 212 | |||||
| 213 | return URI->new($base . $path)->canonical; | ||||
| 214 | } | ||||
| 215 | |||||
| 216 | sub base { | ||||
| 217 | my $self = shift; | ||||
| 218 | URI->new($self->_uri_base)->canonical; | ||||
| 219 | } | ||||
| 220 | |||||
| 221 | sub _uri_base { | ||||
| 222 | my $self = shift; | ||||
| 223 | |||||
| 224 | my $env = $self->env; | ||||
| 225 | |||||
| 226 | my $uri = ($env->{'psgi.url_scheme'} || "http") . | ||||
| 227 | "://" . | ||||
| 228 | ($env->{HTTP_HOST} || (($env->{SERVER_NAME} || "") . ":" . ($env->{SERVER_PORT} || 80))) . | ||||
| 229 | ($env->{SCRIPT_NAME} || '/'); | ||||
| 230 | |||||
| 231 | return $uri; | ||||
| 232 | } | ||||
| 233 | |||||
| 234 | sub new_response { | ||||
| 235 | my $self = shift; | ||||
| 236 | require Plack::Response; | ||||
| 237 | Plack::Response->new(@_); | ||||
| 238 | } | ||||
| 239 | |||||
| 240 | sub _parse_request_body { | ||||
| 241 | my $self = shift; | ||||
| 242 | |||||
| 243 | my $ct = $self->env->{CONTENT_TYPE}; | ||||
| 244 | my $cl = $self->env->{CONTENT_LENGTH}; | ||||
| 245 | if (!$ct && !$cl) { | ||||
| 246 | # No Content-Type nor Content-Length -> GET/HEAD | ||||
| 247 | $self->env->{'plack.request.body'} = Hash::MultiValue->new; | ||||
| 248 | $self->env->{'plack.request.upload'} = Hash::MultiValue->new; | ||||
| 249 | return; | ||||
| 250 | } | ||||
| 251 | |||||
| 252 | my $body = HTTP::Body->new($ct, $cl); | ||||
| 253 | |||||
| 254 | # HTTP::Body will create temporary files in case there was an | ||||
| 255 | # upload. Those temporary files can be cleaned up by telling | ||||
| 256 | # HTTP::Body to do so. It will run the cleanup when the request | ||||
| 257 | # env is destroyed. That the object will not go out of scope by | ||||
| 258 | # the end of this sub we will store a reference here. | ||||
| 259 | $self->env->{'plack.request.http.body'} = $body; | ||||
| 260 | $body->cleanup(1); | ||||
| 261 | |||||
| 262 | my $input = $self->input; | ||||
| 263 | |||||
| 264 | my $buffer; | ||||
| 265 | if ($self->env->{'psgix.input.buffered'}) { | ||||
| 266 | # Just in case if input is read by middleware/apps beforehand | ||||
| 267 | $input->seek(0, 0); | ||||
| 268 | } else { | ||||
| 269 | $buffer = Stream::Buffered->new($cl); | ||||
| 270 | } | ||||
| 271 | |||||
| 272 | my $spin = 0; | ||||
| 273 | while ($cl) { | ||||
| 274 | $input->read(my $chunk, $cl < 8192 ? $cl : 8192); | ||||
| 275 | my $read = length $chunk; | ||||
| 276 | $cl -= $read; | ||||
| 277 | $body->add($chunk); | ||||
| 278 | $buffer->print($chunk) if $buffer; | ||||
| 279 | |||||
| 280 | if ($read == 0 && $spin++ > 2000) { | ||||
| 281 | Carp::croak "Bad Content-Length: maybe client disconnect? ($cl bytes remaining)"; | ||||
| 282 | } | ||||
| 283 | } | ||||
| 284 | |||||
| 285 | if ($buffer) { | ||||
| 286 | $self->env->{'psgix.input.buffered'} = 1; | ||||
| 287 | $self->env->{'psgi.input'} = $buffer->rewind; | ||||
| 288 | } else { | ||||
| 289 | $input->seek(0, 0); | ||||
| 290 | } | ||||
| 291 | |||||
| 292 | $self->env->{'plack.request.body'} = Hash::MultiValue->from_mixed($body->param); | ||||
| 293 | |||||
| 294 | my @uploads = Hash::MultiValue->from_mixed($body->upload)->flatten; | ||||
| 295 | my @obj; | ||||
| 296 | while (my($k, $v) = splice @uploads, 0, 2) { | ||||
| 297 | push @obj, $k, $self->_make_upload($v); | ||||
| 298 | } | ||||
| 299 | |||||
| 300 | $self->env->{'plack.request.upload'} = Hash::MultiValue->new(@obj); | ||||
| 301 | |||||
| 302 | 1; | ||||
| 303 | } | ||||
| 304 | |||||
| 305 | sub _make_upload { | ||||
| 306 | my($self, $upload) = @_; | ||||
| 307 | my %copy = %$upload; | ||||
| 308 | $copy{headers} = HTTP::Headers::Fast->new(%{$upload->{headers}}); | ||||
| 309 | Plack::Request::Upload->new(%copy); | ||||
| 310 | } | ||||
| 311 | |||||
| 312 | 1 | 2µs | 1; | ||
| 313 | __END__ | ||||
sub Plack::Request::CORE:match; # opcode | |||||
# spent 1.18s within Plack::Request::CORE:subst which was called 904221 times, avg 1µs/call:
# 600006 times (973ms+0s) by Plack::Request::headers at line 124, avg 2µs/call
# 204214 times (71.7ms+0s) by Plack::Request::_parse_query at line 90, avg 351ns/call
# 100001 times (133ms+0s) by Plack::Request::_parse_query at line 89, avg 1µs/call |