| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package Mojo::Message::Request; | 
| 2 | 59 |  |  | 59 |  | 65391 | use Mojo::Base 'Mojo::Message'; | 
|  | 59 |  |  |  |  | 134 |  | 
|  | 59 |  |  |  |  | 417 |  | 
| 3 |  |  |  |  |  |  |  | 
| 4 | 59 |  |  | 59 |  | 467 | use Digest::SHA qw(sha1_base64); | 
|  | 59 |  |  |  |  | 155 |  | 
|  | 59 |  |  |  |  | 3552 |  | 
| 5 | 59 |  |  | 59 |  | 7809 | use Mojo::Cookie::Request; | 
|  | 59 |  |  |  |  | 671 |  | 
|  | 59 |  |  |  |  | 735 |  | 
| 6 | 59 |  |  | 59 |  | 407 | use Mojo::Util qw(b64_encode b64_decode sha1_sum); | 
|  | 59 |  |  |  |  | 138 |  | 
|  | 59 |  |  |  |  | 3294 |  | 
| 7 | 59 |  |  | 59 |  | 8653 | use Mojo::URL; | 
|  | 59 |  |  |  |  | 190 |  | 
|  | 59 |  |  |  |  | 714 |  | 
| 8 |  |  |  |  |  |  |  | 
| 9 |  |  |  |  |  |  | has env    => sub { {} }; | 
| 10 |  |  |  |  |  |  | has method => 'GET'; | 
| 11 |  |  |  |  |  |  | has [qw(proxy reverse_proxy)]; | 
| 12 |  |  |  |  |  |  | has request_id => sub { | 
| 13 |  |  |  |  |  |  | state $seed    = $$ . time . rand; | 
| 14 |  |  |  |  |  |  | state $counter = int rand 0xffffff; | 
| 15 |  |  |  |  |  |  | my $b64 = substr(sha1_base64($seed . ($counter = ($counter + 1) % 0xffffff)), 0, 12); | 
| 16 |  |  |  |  |  |  | $b64 =~ tr!+/!-_!; | 
| 17 |  |  |  |  |  |  | return $b64; | 
| 18 |  |  |  |  |  |  | }; | 
| 19 |  |  |  |  |  |  | has trusted_proxies => sub { [] }; | 
| 20 |  |  |  |  |  |  | has url             => sub { Mojo::URL->new }; | 
| 21 |  |  |  |  |  |  | has via_proxy       => 1; | 
| 22 |  |  |  |  |  |  |  | 
| 23 |  |  |  |  |  |  | sub clone { | 
| 24 | 19 |  |  | 19 | 1 | 40 | my $self = shift; | 
| 25 |  |  |  |  |  |  |  | 
| 26 |  |  |  |  |  |  | # Dynamic requests cannot be cloned | 
| 27 | 19 | 100 |  |  |  | 58 | return undef unless my $content = $self->content->clone; | 
| 28 | 15 |  |  |  |  | 65 | my $clone | 
| 29 |  |  |  |  |  |  | = $self->new(content => $content, method => $self->method, url => $self->url->clone, version => $self->version); | 
| 30 | 15 | 100 |  |  |  | 62 | $clone->{proxy} = $self->{proxy}->clone if $self->{proxy}; | 
| 31 |  |  |  |  |  |  |  | 
| 32 | 15 |  |  |  |  | 378 | return $clone; | 
| 33 |  |  |  |  |  |  | } | 
| 34 |  |  |  |  |  |  |  | 
| 35 |  |  |  |  |  |  | sub cookies { | 
| 36 | 404 |  |  | 404 | 1 | 794 | my $self = shift; | 
| 37 |  |  |  |  |  |  |  | 
| 38 |  |  |  |  |  |  | # Parse cookies | 
| 39 | 404 |  |  |  |  | 1225 | my $headers = $self->headers; | 
| 40 | 404 | 100 |  |  |  | 1578 | return [map { @{Mojo::Cookie::Request->parse($_)} } $headers->cookie] unless @_; | 
|  | 179 |  |  |  |  | 338 |  | 
|  | 179 |  |  |  |  | 1056 |  | 
| 41 |  |  |  |  |  |  |  | 
| 42 |  |  |  |  |  |  | # Add cookies | 
| 43 | 225 | 100 | 100 |  |  | 817 | my @cookies = map { ref $_ eq 'HASH' ? Mojo::Cookie::Request->new($_) : $_ } $headers->cookie || (), @_; | 
|  | 392 |  |  |  |  | 1356 |  | 
| 44 | 225 |  |  |  |  | 1749 | $headers->cookie(join '; ', @cookies); | 
| 45 |  |  |  |  |  |  |  | 
| 46 | 225 |  |  |  |  | 1327 | return $self; | 
| 47 |  |  |  |  |  |  | } | 
| 48 |  |  |  |  |  |  |  | 
| 49 | 302 |  |  | 302 | 1 | 833 | sub every_param { shift->params->every_param(@_) } | 
| 50 |  |  |  |  |  |  |  | 
| 51 |  |  |  |  |  |  | sub extract_start_line { | 
| 52 | 1060 |  |  | 1060 | 1 | 2452 | my ($self, $bufref) = @_; | 
| 53 |  |  |  |  |  |  |  | 
| 54 |  |  |  |  |  |  | # Ignore any leading empty lines | 
| 55 | 1060 | 100 |  |  |  | 12082 | return undef unless $$bufref =~ s/^\s*(.*?)\x0d?\x0a//; | 
| 56 |  |  |  |  |  |  |  | 
| 57 |  |  |  |  |  |  | # We have a (hopefully) full request-line | 
| 58 | 1035 | 100 |  |  |  | 7642 | return !$self->error({message => 'Bad request start-line'}) unless $1 =~ /^(\S+)\s+(\S+)\s+HTTP\/(\d\.\d)$/; | 
| 59 | 1034 |  |  |  |  | 3407 | my $url    = $self->method($1)->version($3)->url; | 
| 60 | 1034 |  |  |  |  | 3020 | my $target = $2; | 
| 61 | 1034 | 100 |  |  |  | 3377 | return !!$url->host_port($target)              if $1 eq 'CONNECT'; | 
| 62 | 1032 | 100 |  |  |  | 3144 | return !!$url->parse($target)->fragment(undef) if $target =~ /^[^:\/?#]+:/; | 
| 63 | 1025 |  |  |  |  | 2987 | return !!$url->path_query($target); | 
| 64 |  |  |  |  |  |  | } | 
| 65 |  |  |  |  |  |  |  | 
| 66 |  |  |  |  |  |  | sub fix_headers { | 
| 67 | 1965 |  |  | 1965 | 1 | 3234 | my $self = shift; | 
| 68 | 1965 | 100 |  |  |  | 7691 | $self->{fix} ? return $self : $self->SUPER::fix_headers(@_); | 
| 69 |  |  |  |  |  |  |  | 
| 70 |  |  |  |  |  |  | # Empty | 
| 71 | 983 |  |  |  |  | 2644 | my $headers = $self->headers; | 
| 72 | 983 | 100 | 100 |  |  | 2671 | $headers->remove('Content-Length') if ($headers->content_length // '') eq '0' && $self->method eq 'GET'; | 
|  |  |  | 100 |  |  |  |  | 
| 73 |  |  |  |  |  |  |  | 
| 74 |  |  |  |  |  |  | # Host | 
| 75 | 983 |  |  |  |  | 2695 | my $url = $self->url; | 
| 76 | 983 | 100 |  |  |  | 2965 | $headers->host($url->host_port) unless $headers->host; | 
| 77 |  |  |  |  |  |  |  | 
| 78 |  |  |  |  |  |  | # Basic authentication | 
| 79 | 983 | 100 | 66 |  |  | 3017 | if ((my $info = $url->userinfo) && !$headers->authorization) { | 
| 80 | 6 |  |  |  |  | 59 | $headers->authorization('Basic ' . b64_encode($info, '')); | 
| 81 |  |  |  |  |  |  | } | 
| 82 |  |  |  |  |  |  |  | 
| 83 |  |  |  |  |  |  | # Basic proxy authentication | 
| 84 | 983 | 100 | 100 |  |  | 2705 | return $self                                                    unless (my $proxy = $self->proxy) && $self->via_proxy; | 
| 85 | 14 | 100 |  |  |  | 58 | return $self                                                    unless my $info = $proxy->userinfo; | 
| 86 | 6 | 50 |  |  |  | 27 | $headers->proxy_authorization('Basic ' . b64_encode($info, '')) unless $headers->proxy_authorization; | 
| 87 | 6 |  |  |  |  | 21 | return $self; | 
| 88 |  |  |  |  |  |  | } | 
| 89 |  |  |  |  |  |  |  | 
| 90 |  |  |  |  |  |  | sub get_start_line_chunk { | 
| 91 | 1014 |  |  | 1014 | 1 | 2269 | my ($self, $offset) = @_; | 
| 92 | 1014 |  |  |  |  | 2335 | $self->_start_line->emit(progress => 'start_line', $offset); | 
| 93 | 1014 |  |  |  |  | 3966 | return substr $self->{start_buffer}, $offset, 131072; | 
| 94 |  |  |  |  |  |  | } | 
| 95 |  |  |  |  |  |  |  | 
| 96 | 4749 |  | 100 | 4749 | 1 | 13594 | sub is_handshake { lc($_[0]->headers->upgrade // '') eq 'websocket' } | 
| 97 |  |  |  |  |  |  |  | 
| 98 |  |  |  |  |  |  | sub is_secure { | 
| 99 | 3 |  |  | 3 | 1 | 20 | my $url = shift->url; | 
| 100 | 3 |  | 33 |  |  | 12 | return ($url->protocol || $url->base->protocol) eq 'https'; | 
| 101 |  |  |  |  |  |  | } | 
| 102 |  |  |  |  |  |  |  | 
| 103 | 2 |  | 100 | 2 | 1 | 20 | sub is_xhr { (shift->headers->header('X-Requested-With') // '') =~ /XMLHttpRequest/i } | 
| 104 |  |  |  |  |  |  |  | 
| 105 | 285 |  |  | 285 | 1 | 740 | sub param { shift->params->param(@_) } | 
| 106 |  |  |  |  |  |  |  | 
| 107 | 735 |  | 66 | 735 | 1 | 3858 | sub params { $_[0]->{params} ||= $_[0]->body_params->clone->append($_[0]->query_params) } | 
| 108 |  |  |  |  |  |  |  | 
| 109 |  |  |  |  |  |  | sub parse { | 
| 110 | 1510 | 100 |  | 1510 | 1 | 19829 | my ($self, $env, $chunk) = (shift, ref $_[0] ? (shift, '') : (undef, shift)); | 
| 111 |  |  |  |  |  |  |  | 
| 112 |  |  |  |  |  |  | # Parse CGI environment | 
| 113 | 1510 | 100 |  |  |  | 3495 | $self->env($env)->_parse_env($env) if $env; | 
| 114 |  |  |  |  |  |  |  | 
| 115 |  |  |  |  |  |  | # Parse normal message | 
| 116 | 1510 | 100 | 100 |  |  | 6308 | if (($self->{state} // '') ne 'cgi') { $self->SUPER::parse($chunk) } | 
|  | 1455 |  |  |  |  | 4437 |  | 
| 117 |  |  |  |  |  |  |  | 
| 118 |  |  |  |  |  |  | # Parse CGI content | 
| 119 | 55 |  |  |  |  | 164 | else { $self->content($self->content->parse_body($chunk))->SUPER::parse('') } | 
| 120 |  |  |  |  |  |  |  | 
| 121 |  |  |  |  |  |  | # Check if we can fix things that require all headers | 
| 122 | 1510 | 100 |  |  |  | 4792 | return $self unless $self->is_finished; | 
| 123 |  |  |  |  |  |  |  | 
| 124 |  |  |  |  |  |  | # Base URL | 
| 125 | 1089 |  |  |  |  | 3196 | my $base = $self->url->base; | 
| 126 | 1089 | 100 |  |  |  | 3366 | $base->scheme('http') unless $base->scheme; | 
| 127 | 1089 |  |  |  |  | 3044 | my $headers = $self->headers; | 
| 128 | 1089 | 100 | 100 |  |  | 3041 | if (!$base->host && (my $host = $headers->host)) { $base->host_port($host) } | 
|  | 990 |  |  |  |  | 3016 |  | 
| 129 |  |  |  |  |  |  |  | 
| 130 |  |  |  |  |  |  | # Basic authentication | 
| 131 | 1089 | 100 |  |  |  | 3848 | if (my $basic = _basic($headers->authorization)) { $base->userinfo($basic) } | 
|  | 7 |  |  |  |  | 41 |  | 
| 132 |  |  |  |  |  |  |  | 
| 133 |  |  |  |  |  |  | # Basic proxy authentication | 
| 134 | 1089 |  |  |  |  | 3021 | my $basic = _basic($headers->proxy_authorization); | 
| 135 | 1089 | 100 |  |  |  | 2661 | $self->proxy(Mojo::URL->new->userinfo($basic)) if $basic; | 
| 136 |  |  |  |  |  |  |  | 
| 137 |  |  |  |  |  |  | # "X-Forwarded-Proto" | 
| 138 | 1089 | 100 | 100 |  |  | 3214 | $base->scheme('https') if $self->reverse_proxy && ($headers->header('X-Forwarded-Proto') // '') eq 'https'; | 
|  |  |  | 100 |  |  |  |  | 
| 139 |  |  |  |  |  |  |  | 
| 140 | 1089 |  |  |  |  | 3370 | return $self; | 
| 141 |  |  |  |  |  |  | } | 
| 142 |  |  |  |  |  |  |  | 
| 143 | 323 |  |  | 323 | 1 | 1041 | sub query_params { shift->url->query } | 
| 144 |  |  |  |  |  |  |  | 
| 145 | 948 |  |  | 948 | 1 | 3347 | sub start_line_size { length shift->_start_line->{start_buffer} } | 
| 146 |  |  |  |  |  |  |  | 
| 147 | 2178 | 100 | 66 | 2178 |  | 7197 | sub _basic { $_[0] && $_[0] =~ /Basic (.+)$/ ? b64_decode $1 : undef } | 
| 148 |  |  |  |  |  |  |  | 
| 149 |  |  |  |  |  |  | sub _parse_env { | 
| 150 | 32 |  |  | 32 |  | 80 | my ($self, $env) = @_; | 
| 151 |  |  |  |  |  |  |  | 
| 152 |  |  |  |  |  |  | # Bypass normal message parser | 
| 153 | 32 |  |  |  |  | 81 | $self->{state} = 'cgi'; | 
| 154 |  |  |  |  |  |  |  | 
| 155 |  |  |  |  |  |  | # Extract headers | 
| 156 | 32 |  |  |  |  | 107 | my $headers = $self->headers; | 
| 157 | 32 |  |  |  |  | 96 | my $url     = $self->url; | 
| 158 | 32 |  |  |  |  | 101 | my $base    = $url->base; | 
| 159 | 32 |  |  |  |  | 149 | for my $name (keys %$env) { | 
| 160 | 330 |  |  |  |  | 539 | my $value = $env->{$name}; | 
| 161 | 330 | 100 |  |  |  | 901 | next unless $name =~ s/^HTTP_//i; | 
| 162 | 59 |  |  |  |  | 133 | $name =~ y/_/-/; | 
| 163 | 59 |  |  |  |  | 210 | $headers->header($name => $value); | 
| 164 |  |  |  |  |  |  |  | 
| 165 |  |  |  |  |  |  | # Host/Port | 
| 166 | 59 | 100 |  |  |  | 335 | $value =~ s/:(\d+)$// ? $base->host($value)->port($1) : $base->host($value) if $name eq 'HOST'; | 
|  |  | 100 |  |  |  |  |  | 
| 167 |  |  |  |  |  |  | } | 
| 168 |  |  |  |  |  |  |  | 
| 169 |  |  |  |  |  |  | # Content-Type is a special case on some servers | 
| 170 | 32 | 100 |  |  |  | 159 | $headers->content_type($env->{CONTENT_TYPE}) if $env->{CONTENT_TYPE}; | 
| 171 |  |  |  |  |  |  |  | 
| 172 |  |  |  |  |  |  | # Content-Length is a special case on some servers | 
| 173 | 32 | 100 |  |  |  | 118 | $headers->content_length($env->{CONTENT_LENGTH}) if $env->{CONTENT_LENGTH}; | 
| 174 |  |  |  |  |  |  |  | 
| 175 |  |  |  |  |  |  | # Query | 
| 176 | 32 | 100 |  |  |  | 90 | $url->query->parse($env->{QUERY_STRING}) if $env->{QUERY_STRING}; | 
| 177 |  |  |  |  |  |  |  | 
| 178 |  |  |  |  |  |  | # Method | 
| 179 | 32 | 50 |  |  |  | 146 | $self->method($env->{REQUEST_METHOD}) if $env->{REQUEST_METHOD}; | 
| 180 |  |  |  |  |  |  |  | 
| 181 |  |  |  |  |  |  | # Scheme/Version | 
| 182 | 32 | 50 | 33 |  |  | 259 | $base->scheme($1) and $self->version($2) if ($env->{SERVER_PROTOCOL} // '') =~ m!^([^/]+)/([^/]+)$!; | 
|  |  |  | 50 |  |  |  |  | 
| 183 |  |  |  |  |  |  |  | 
| 184 |  |  |  |  |  |  | # HTTPS | 
| 185 | 32 | 100 | 100 |  |  | 168 | $base->scheme('https') if uc($env->{HTTPS} // '') eq 'ON'; | 
| 186 |  |  |  |  |  |  |  | 
| 187 |  |  |  |  |  |  | # Path | 
| 188 | 32 | 100 |  |  |  | 129 | my $path = $url->path->parse($env->{PATH_INFO} ? $env->{PATH_INFO} : ''); | 
| 189 |  |  |  |  |  |  |  | 
| 190 |  |  |  |  |  |  | # Base path | 
| 191 | 32 | 100 |  |  |  | 88 | if (my $value = $env->{SCRIPT_NAME}) { | 
| 192 |  |  |  |  |  |  |  | 
| 193 |  |  |  |  |  |  | # Make sure there is a trailing slash (important for merging) | 
| 194 | 30 | 100 |  |  |  | 76 | $base->path->parse($value =~ m!/$! ? $value : "$value/"); | 
| 195 |  |  |  |  |  |  |  | 
| 196 |  |  |  |  |  |  | # Remove SCRIPT_NAME prefix if necessary | 
| 197 | 30 |  |  |  |  | 95 | my $buffer = $path->to_string; | 
| 198 | 30 |  |  |  |  | 134 | $value  =~ s!^/|/$!!g; | 
| 199 | 30 |  |  |  |  | 349 | $buffer =~ s!^/?\Q$value\E/?!!; | 
| 200 | 30 |  |  |  |  | 105 | $buffer =~ s!^/!!; | 
| 201 | 30 |  |  |  |  | 99 | $path->parse($buffer); | 
| 202 |  |  |  |  |  |  | } | 
| 203 |  |  |  |  |  |  | } | 
| 204 |  |  |  |  |  |  |  | 
| 205 |  |  |  |  |  |  | sub _start_line { | 
| 206 | 1962 |  |  | 1962 |  | 3442 | my $self = shift; | 
| 207 |  |  |  |  |  |  |  | 
| 208 | 1962 | 100 |  |  |  | 7848 | return $self if defined $self->{start_buffer}; | 
| 209 |  |  |  |  |  |  |  | 
| 210 |  |  |  |  |  |  | # Path | 
| 211 | 980 |  |  |  |  | 2588 | my $url  = $self->url; | 
| 212 | 980 |  |  |  |  | 3450 | my $path = $url->path_query; | 
| 213 | 980 | 100 |  |  |  | 4631 | $path = "/$path" unless $path =~ m!^/!; | 
| 214 |  |  |  |  |  |  |  | 
| 215 |  |  |  |  |  |  | # CONNECT | 
| 216 | 980 |  |  |  |  | 3251 | my $method = uc $self->method; | 
| 217 | 980 | 100 | 100 |  |  | 4011 | if ($method eq 'CONNECT') { | 
|  |  | 100 | 100 |  |  |  |  | 
| 218 | 3 | 0 | 33 |  |  | 15 | my $port = $url->port // ($url->protocol eq 'https' ? '443' : '80'); | 
| 219 | 3 |  |  |  |  | 13 | $path = $url->ihost . ":$port"; | 
| 220 |  |  |  |  |  |  | } | 
| 221 |  |  |  |  |  |  |  | 
| 222 |  |  |  |  |  |  | # Proxy | 
| 223 |  |  |  |  |  |  | elsif ($self->proxy && $self->via_proxy && $url->protocol ne 'https') { | 
| 224 | 8 | 100 |  |  |  | 37 | $path = $url->clone->userinfo(undef) unless $self->is_handshake; | 
| 225 |  |  |  |  |  |  | } | 
| 226 |  |  |  |  |  |  |  | 
| 227 | 980 |  |  |  |  | 3020 | $self->{start_buffer} = "$method $path HTTP/@{[$self->version]}\x0d\x0a"; | 
|  | 980 |  |  |  |  | 3088 |  | 
| 228 |  |  |  |  |  |  |  | 
| 229 | 980 |  |  |  |  | 5469 | return $self; | 
| 230 |  |  |  |  |  |  | } | 
| 231 |  |  |  |  |  |  |  | 
| 232 |  |  |  |  |  |  | 1; | 
| 233 |  |  |  |  |  |  |  | 
| 234 |  |  |  |  |  |  | =encoding utf8 | 
| 235 |  |  |  |  |  |  |  | 
| 236 |  |  |  |  |  |  | =head1 NAME | 
| 237 |  |  |  |  |  |  |  | 
| 238 |  |  |  |  |  |  | Mojo::Message::Request - HTTP request | 
| 239 |  |  |  |  |  |  |  | 
| 240 |  |  |  |  |  |  | =head1 SYNOPSIS | 
| 241 |  |  |  |  |  |  |  | 
| 242 |  |  |  |  |  |  | use Mojo::Message::Request; | 
| 243 |  |  |  |  |  |  |  | 
| 244 |  |  |  |  |  |  | # Parse | 
| 245 |  |  |  |  |  |  | my $req = Mojo::Message::Request->new; | 
| 246 |  |  |  |  |  |  | $req->parse("GET /foo HTTP/1.0\x0d\x0a"); | 
| 247 |  |  |  |  |  |  | $req->parse("Content-Length: 12\x0d\x0a"); | 
| 248 |  |  |  |  |  |  | $req->parse("Content-Type: text/plain\x0d\x0a\x0d\x0a"); | 
| 249 |  |  |  |  |  |  | $req->parse('Hello World!'); | 
| 250 |  |  |  |  |  |  | say $req->method; | 
| 251 |  |  |  |  |  |  | say $req->headers->content_type; | 
| 252 |  |  |  |  |  |  | say $req->body; | 
| 253 |  |  |  |  |  |  |  | 
| 254 |  |  |  |  |  |  | # Build | 
| 255 |  |  |  |  |  |  | my $req = Mojo::Message::Request->new; | 
| 256 |  |  |  |  |  |  | $req->url->parse('http://127.0.0.1/foo/bar'); | 
| 257 |  |  |  |  |  |  | $req->method('GET'); | 
| 258 |  |  |  |  |  |  | say $req->to_string; | 
| 259 |  |  |  |  |  |  |  | 
| 260 |  |  |  |  |  |  | =head1 DESCRIPTION | 
| 261 |  |  |  |  |  |  |  | 
| 262 |  |  |  |  |  |  | L is a container for HTTP requests, based on L, | 
| 263 |  |  |  |  |  |  | L, L and L | 
| 264 |  |  |  |  |  |  | 2817|https://tools.ietf.org/html/rfc2817>. | 
| 265 |  |  |  |  |  |  |  | 
| 266 |  |  |  |  |  |  | =head1 EVENTS | 
| 267 |  |  |  |  |  |  |  | 
| 268 |  |  |  |  |  |  | L inherits all events from L. | 
| 269 |  |  |  |  |  |  |  | 
| 270 |  |  |  |  |  |  | =head1 ATTRIBUTES | 
| 271 |  |  |  |  |  |  |  | 
| 272 |  |  |  |  |  |  | L inherits all attributes from L and implements the following new ones. | 
| 273 |  |  |  |  |  |  |  | 
| 274 |  |  |  |  |  |  | =head2 env | 
| 275 |  |  |  |  |  |  |  | 
| 276 |  |  |  |  |  |  | my $env = $req->env; | 
| 277 |  |  |  |  |  |  | $req    = $req->env({PATH_INFO => '/'}); | 
| 278 |  |  |  |  |  |  |  | 
| 279 |  |  |  |  |  |  | Direct access to the C or C environment hash if available. | 
| 280 |  |  |  |  |  |  |  | 
| 281 |  |  |  |  |  |  | # Check CGI version | 
| 282 |  |  |  |  |  |  | my $version = $req->env->{GATEWAY_INTERFACE}; | 
| 283 |  |  |  |  |  |  |  | 
| 284 |  |  |  |  |  |  | # Check PSGI version | 
| 285 |  |  |  |  |  |  | my $version = $req->env->{'psgi.version'}; | 
| 286 |  |  |  |  |  |  |  | 
| 287 |  |  |  |  |  |  | =head2 method | 
| 288 |  |  |  |  |  |  |  | 
| 289 |  |  |  |  |  |  | my $method = $req->method; | 
| 290 |  |  |  |  |  |  | $req       = $req->method('POST'); | 
| 291 |  |  |  |  |  |  |  | 
| 292 |  |  |  |  |  |  | HTTP request method, defaults to C. | 
| 293 |  |  |  |  |  |  |  | 
| 294 |  |  |  |  |  |  | =head2 proxy | 
| 295 |  |  |  |  |  |  |  | 
| 296 |  |  |  |  |  |  | my $url = $req->proxy; | 
| 297 |  |  |  |  |  |  | $req    = $req->proxy(Mojo::URL->new('http://127.0.0.1:3000')); | 
| 298 |  |  |  |  |  |  |  | 
| 299 |  |  |  |  |  |  | Proxy URL for request. | 
| 300 |  |  |  |  |  |  |  | 
| 301 |  |  |  |  |  |  | =head2 reverse_proxy | 
| 302 |  |  |  |  |  |  |  | 
| 303 |  |  |  |  |  |  | my $bool = $req->reverse_proxy; | 
| 304 |  |  |  |  |  |  | $req     = $req->reverse_proxy($bool); | 
| 305 |  |  |  |  |  |  |  | 
| 306 |  |  |  |  |  |  | Request has been performed through a reverse proxy. | 
| 307 |  |  |  |  |  |  |  | 
| 308 |  |  |  |  |  |  | =head2 trusted_proxies | 
| 309 |  |  |  |  |  |  |  | 
| 310 |  |  |  |  |  |  | my $proxies = $req->trusted_proxies; | 
| 311 |  |  |  |  |  |  | $req        = $req->trusted_proxies(['10.0.0.0/8', '127.0.0.1', '172.16.0.0/12', '192.168.0.0/16', 'fc00::/7']); | 
| 312 |  |  |  |  |  |  |  | 
| 313 |  |  |  |  |  |  | Trusted reverse proxies, addresses or networks in CIDR form. | 
| 314 |  |  |  |  |  |  |  | 
| 315 |  |  |  |  |  |  | =head2 request_id | 
| 316 |  |  |  |  |  |  |  | 
| 317 |  |  |  |  |  |  | my $id = $req->request_id; | 
| 318 |  |  |  |  |  |  | $req   = $req->request_id('aee7d5d8'); | 
| 319 |  |  |  |  |  |  |  | 
| 320 |  |  |  |  |  |  | Request ID, defaults to a reasonably unique value. | 
| 321 |  |  |  |  |  |  |  | 
| 322 |  |  |  |  |  |  | =head2 url | 
| 323 |  |  |  |  |  |  |  | 
| 324 |  |  |  |  |  |  | my $url = $req->url; | 
| 325 |  |  |  |  |  |  | $req    = $req->url(Mojo::URL->new); | 
| 326 |  |  |  |  |  |  |  | 
| 327 |  |  |  |  |  |  | HTTP request URL, defaults to a L object. | 
| 328 |  |  |  |  |  |  |  | 
| 329 |  |  |  |  |  |  | # Get request information | 
| 330 |  |  |  |  |  |  | my $info = $req->url->to_abs->userinfo; | 
| 331 |  |  |  |  |  |  | my $host = $req->url->to_abs->host; | 
| 332 |  |  |  |  |  |  | my $path = $req->url->to_abs->path; | 
| 333 |  |  |  |  |  |  |  | 
| 334 |  |  |  |  |  |  | =head2 via_proxy | 
| 335 |  |  |  |  |  |  |  | 
| 336 |  |  |  |  |  |  | my $bool = $req->via_proxy; | 
| 337 |  |  |  |  |  |  | $req     = $req->via_proxy($bool); | 
| 338 |  |  |  |  |  |  |  | 
| 339 |  |  |  |  |  |  | Request can be performed through a proxy server. | 
| 340 |  |  |  |  |  |  |  | 
| 341 |  |  |  |  |  |  | =head1 METHODS | 
| 342 |  |  |  |  |  |  |  | 
| 343 |  |  |  |  |  |  | L inherits all methods from L and implements the following new ones. | 
| 344 |  |  |  |  |  |  |  | 
| 345 |  |  |  |  |  |  | =head2 clone | 
| 346 |  |  |  |  |  |  |  | 
| 347 |  |  |  |  |  |  | my $clone = $req->clone; | 
| 348 |  |  |  |  |  |  |  | 
| 349 |  |  |  |  |  |  | Return a new L object cloned from this request if possible, otherwise return C. | 
| 350 |  |  |  |  |  |  |  | 
| 351 |  |  |  |  |  |  | =head2 cookies | 
| 352 |  |  |  |  |  |  |  | 
| 353 |  |  |  |  |  |  | my $cookies = $req->cookies; | 
| 354 |  |  |  |  |  |  | $req        = $req->cookies(Mojo::Cookie::Request->new); | 
| 355 |  |  |  |  |  |  | $req        = $req->cookies({name => 'foo', value => 'bar'}); | 
| 356 |  |  |  |  |  |  |  | 
| 357 |  |  |  |  |  |  | Access request cookies, usually L objects. | 
| 358 |  |  |  |  |  |  |  | 
| 359 |  |  |  |  |  |  | # Names of all cookies | 
| 360 |  |  |  |  |  |  | say $_->name for @{$req->cookies}; | 
| 361 |  |  |  |  |  |  |  | 
| 362 |  |  |  |  |  |  | =head2 every_param | 
| 363 |  |  |  |  |  |  |  | 
| 364 |  |  |  |  |  |  | my $values = $req->every_param('foo'); | 
| 365 |  |  |  |  |  |  |  | 
| 366 |  |  |  |  |  |  | Similar to L"param">, but returns all values sharing the same name as an array reference. | 
| 367 |  |  |  |  |  |  |  | 
| 368 |  |  |  |  |  |  | # Get first value | 
| 369 |  |  |  |  |  |  | say $req->every_param('foo')->[0]; | 
| 370 |  |  |  |  |  |  |  | 
| 371 |  |  |  |  |  |  | =head2 extract_start_line | 
| 372 |  |  |  |  |  |  |  | 
| 373 |  |  |  |  |  |  | my $bool = $req->extract_start_line(\$str); | 
| 374 |  |  |  |  |  |  |  | 
| 375 |  |  |  |  |  |  | Extract request-line from string. | 
| 376 |  |  |  |  |  |  |  | 
| 377 |  |  |  |  |  |  | =head2 fix_headers | 
| 378 |  |  |  |  |  |  |  | 
| 379 |  |  |  |  |  |  | $req = $req->fix_headers; | 
| 380 |  |  |  |  |  |  |  | 
| 381 |  |  |  |  |  |  | Make sure request has all required headers. | 
| 382 |  |  |  |  |  |  |  | 
| 383 |  |  |  |  |  |  | =head2 get_start_line_chunk | 
| 384 |  |  |  |  |  |  |  | 
| 385 |  |  |  |  |  |  | my $bytes = $req->get_start_line_chunk($offset); | 
| 386 |  |  |  |  |  |  |  | 
| 387 |  |  |  |  |  |  | Get a chunk of request-line data starting from a specific position. Note that this method finalizes the request. | 
| 388 |  |  |  |  |  |  |  | 
| 389 |  |  |  |  |  |  | =head2 is_handshake | 
| 390 |  |  |  |  |  |  |  | 
| 391 |  |  |  |  |  |  | my $bool = $req->is_handshake; | 
| 392 |  |  |  |  |  |  |  | 
| 393 |  |  |  |  |  |  | Check C header for C value. | 
| 394 |  |  |  |  |  |  |  | 
| 395 |  |  |  |  |  |  | =head2 is_secure | 
| 396 |  |  |  |  |  |  |  | 
| 397 |  |  |  |  |  |  | my $bool = $req->is_secure; | 
| 398 |  |  |  |  |  |  |  | 
| 399 |  |  |  |  |  |  | Check if connection is secure. | 
| 400 |  |  |  |  |  |  |  | 
| 401 |  |  |  |  |  |  | =head2 is_xhr | 
| 402 |  |  |  |  |  |  |  | 
| 403 |  |  |  |  |  |  | my $bool = $req->is_xhr; | 
| 404 |  |  |  |  |  |  |  | 
| 405 |  |  |  |  |  |  | Check C header for C value. | 
| 406 |  |  |  |  |  |  |  | 
| 407 |  |  |  |  |  |  | =head2 param | 
| 408 |  |  |  |  |  |  |  | 
| 409 |  |  |  |  |  |  | my $value = $req->param('foo'); | 
| 410 |  |  |  |  |  |  |  | 
| 411 |  |  |  |  |  |  | Access C and C parameters extracted from the query string and C or | 
| 412 |  |  |  |  |  |  | C message body. If there are multiple values sharing the same name, and you want to access more | 
| 413 |  |  |  |  |  |  | than just the last one, you can use L"every_param">. Note that this method caches all data, so it should not be | 
| 414 |  |  |  |  |  |  | called before the entire request body has been received. Parts of the request body need to be loaded into memory to | 
| 415 |  |  |  |  |  |  | parse C parameters, so you have to make sure it is not excessively large. There's a 16MiB limit for requests by | 
| 416 |  |  |  |  |  |  | default. | 
| 417 |  |  |  |  |  |  |  | 
| 418 |  |  |  |  |  |  | =head2 params | 
| 419 |  |  |  |  |  |  |  | 
| 420 |  |  |  |  |  |  | my $params = $req->params; | 
| 421 |  |  |  |  |  |  |  | 
| 422 |  |  |  |  |  |  | All C and C parameters extracted from the query string and C or | 
| 423 |  |  |  |  |  |  | C message body, usually a L object. Note that this method caches all data, so it | 
| 424 |  |  |  |  |  |  | should not be called before the entire request body has been received. Parts of the request body need to be loaded into | 
| 425 |  |  |  |  |  |  | memory to parse C parameters, so you have to make sure it is not excessively large. There's a 16MiB limit for | 
| 426 |  |  |  |  |  |  | requests by default. | 
| 427 |  |  |  |  |  |  |  | 
| 428 |  |  |  |  |  |  | # Get parameter names and values | 
| 429 |  |  |  |  |  |  | my $hash = $req->params->to_hash; | 
| 430 |  |  |  |  |  |  |  | 
| 431 |  |  |  |  |  |  | =head2 parse | 
| 432 |  |  |  |  |  |  |  | 
| 433 |  |  |  |  |  |  | $req = $req->parse('GET /foo/bar HTTP/1.1'); | 
| 434 |  |  |  |  |  |  | $req = $req->parse({PATH_INFO => '/'}); | 
| 435 |  |  |  |  |  |  |  | 
| 436 |  |  |  |  |  |  | Parse HTTP request chunks or environment hash. | 
| 437 |  |  |  |  |  |  |  | 
| 438 |  |  |  |  |  |  | =head2 query_params | 
| 439 |  |  |  |  |  |  |  | 
| 440 |  |  |  |  |  |  | my $params = $req->query_params; | 
| 441 |  |  |  |  |  |  |  | 
| 442 |  |  |  |  |  |  | All C parameters, usually a L object. | 
| 443 |  |  |  |  |  |  |  | 
| 444 |  |  |  |  |  |  | # Turn GET parameters to hash and extract value | 
| 445 |  |  |  |  |  |  | say $req->query_params->to_hash->{foo}; | 
| 446 |  |  |  |  |  |  |  | 
| 447 |  |  |  |  |  |  | =head2 start_line_size | 
| 448 |  |  |  |  |  |  |  | 
| 449 |  |  |  |  |  |  | my $size = $req->start_line_size; | 
| 450 |  |  |  |  |  |  |  | 
| 451 |  |  |  |  |  |  | Size of the request-line in bytes. Note that this method finalizes the request. | 
| 452 |  |  |  |  |  |  |  | 
| 453 |  |  |  |  |  |  | =head1 SEE ALSO | 
| 454 |  |  |  |  |  |  |  | 
| 455 |  |  |  |  |  |  | L, L, L. | 
| 456 |  |  |  |  |  |  |  | 
| 457 |  |  |  |  |  |  | =cut |