--- AnyEvent-HTTP/HTTP.pm 2013/11/18 01:01:02 1.118 +++ AnyEvent-HTTP/HTTP.pm 2015/05/08 17:28:39 1.122 @@ -48,7 +48,7 @@ use base Exporter::; -our $VERSION = '2.15'; +our $VERSION = 2.21; our @EXPORT = qw(http_get http_post http_head http_request); @@ -159,6 +159,11 @@ Whether to recurse requests or not, e.g. on redirects, authentication and other retries and so on, and how often to do so. +Only redirects to http and https URLs are supported. While most common +redirection forms are handled entirely within this module, some require +the use of the optional L module. If it is required but missing, then +the request will fail with an error. + =item headers => hashref The request headers to use. Currently, C may provide its own @@ -843,7 +848,7 @@ "$method $rpath HTTP/1.1\015\012" . (join "", map "\u$_: $hdr{$_}\015\012", grep defined $hdr{$_}, keys %hdr) . "\015\012" - . (delete $arg{body}) + . $arg{body} ); # return if error occurred during push_write() @@ -883,19 +888,42 @@ } # redirect handling - # microsoft and other shitheads don't give a shit for following standards, - # try to support some common forms of broken Location headers. - if ($hdr{location} !~ /^(?: $ | [^:\/?\#]+ : )/x) { - $hdr{location} =~ s/^\.\/+//; - - my $url = "$rscheme://$uhost:$uport"; - - unless ($hdr{location} =~ s/^\///) { - $url .= $upath; - $url =~ s/\/[^\/]*$//; + # relative uri handling forced by microsoft and other shitheads. + # we give our best and fall back to URI if available. + if (exists $hdr{location}) { + my $loc = $hdr{location}; + + if ($loc =~ m%^//%) { # // + $loc = "$rscheme:$loc"; + + } elsif ($loc eq "") { + $loc = $url; + + } elsif ($loc !~ /^(?: $ | [^:\/?\#]+ : )/x) { # anything "simple" + $loc =~ s/^\.\/+//; + + if ($loc !~ m%^[.?#]%) { + my $prefix = "$rscheme://$uhost:$uport"; + + unless ($loc =~ s/^\///) { + $prefix .= $upath; + $prefix =~ s/\/[^\/]*$//; + } + + $loc = "$prefix/$loc"; + + } elsif (eval { require URI }) { # uri + $loc = URI->new_abs ($loc, $url)->as_string; + + } else { + return _error %state, $cb, { @pseudo, Status => 599, Reason => "Cannot parse Location (URI module missing)" }; + #$hdr{Status} = 599; + #$hdr{Reason} = "Unparsable Redirect (URI module missing)"; + #$recurse = 0; + } } - $hdr{location} = "$url/$hdr{location}"; + $hdr{location} = $loc; } my $redirect; @@ -907,12 +935,16 @@ # 301, 302 and 303, in contrast to HTTP/1.0 and 1.1. # also, the UA should ask the user for 301 and 307 and POST, # industry standard seems to be to simply follow. - # we go with the industry standard. + # we go with the industry standard. 308 is defined + # by rfc7538 if ($status == 301 or $status == 302 or $status == 303) { - # HTTP/1.1 is unclear on how to mutate the method - $method = "GET" unless $method eq "HEAD"; $redirect = 1; - } elsif ($status == 307) { + # HTTP/1.1 is unclear on how to mutate the method + unless ($method eq "HEAD") { + $method = "GET"; + delete $arg{body}; + } + } elsif ($status == 307 or $status == 308) { $redirect = 1; } } @@ -1149,8 +1181,12 @@ if ($proxy && $uscheme eq "https") { # oh dear, we have to wrap it into a connect request + my $auth = exists $hdr{"proxy-authorization"} + ? "proxy-authorization: " . (delete $hdr{"proxy-authorization"}) . "\015\012" + : ""; + # maybe re-use $uauthority with patched port? - $state{handle}->push_write ("CONNECT $uhost:$uport HTTP/1.0\015\012\015\012"); + $state{handle}->push_write ("CONNECT $uhost:$uport HTTP/1.0\015\012$auth\015\012"); $state{handle}->push_read (line => $qr_nlnl, sub { $_[1] =~ /^HTTP\/([0-9\.]+) \s+ ([0-9]{3}) (?: \s+ ([^\015\012]*) )?/ix or return _error %state, $cb, { @pseudo, Status => 599, Reason => "Invalid proxy connect response ($_[1])" }; @@ -1163,6 +1199,8 @@ } }); } else { + delete $hdr{"proxy-authorization"} unless $proxy; + $handle_actual_request->(); } }; @@ -1250,7 +1288,7 @@ function from time to time. A cookie jar is initially an empty hash-reference that is managed by this -module. It's format is subject to change, but currently it is like this: +module. Its format is subject to change, but currently it is as follows: The key C has to contain C<1>, otherwise the hash gets emptied. All other keys are hostnames or IP addresses pointing to @@ -1305,7 +1343,7 @@ =item $AnyEvent::HTTP::MAX_PER_HOST The maximum number of concurrent connections to the same host (identified -by the hostname). If the limit is exceeded, then the additional requests +by the hostname). If the limit is exceeded, then additional requests are queued until previous connections are closed. Both persistent and non-persistent connections are counted in this limit.