--- AnyEvent-HTTP/HTTP.pm 2009/07/06 03:03:12 1.43 +++ AnyEvent-HTTP/HTTP.pm 2009/12/05 15:37:07 1.53 @@ -43,14 +43,14 @@ use Errno (); -use AnyEvent 4.452 (); +use AnyEvent 5.0 (); use AnyEvent::Util (); use AnyEvent::Socket (); use AnyEvent::Handle (); use base Exporter::; -our $VERSION = '1.12'; +our $VERSION = '1.44'; our @EXPORT = qw(http_get http_post http_head http_request); @@ -140,19 +140,24 @@ The request headers to use. Currently, C may provide its own C, C, C and C headers -and will provide defaults for C and C. +and will provide defaults for C and C (this can be +suppressed by using C for these headers in which case they won't be +sent at all). =item timeout => $seconds The time-out to use for various stages - each connect attempt will reset -the timeout, as will read or write activity. Default timeout is 5 minutes. +the timeout, as will read or write activity, i.e. this is not an overall +timeout. + +Default timeout is 5 minutes. =item proxy => [$host, $port[, $scheme]] or undef Use the given http proxy for all requests. If not specified, then the default proxy (as specified by C<$ENV{http_proxy}>) is used. -C<$scheme> must be either missing or C for HTTP, or C for +C<$scheme> must be either missing, C for HTTP or C for HTTPS. =item body => $string @@ -188,6 +193,15 @@ The default for this option is C, which could be interpreted as "give me the page, no matter what". +=item on_prepare => $callback->($fh) + +In rare cases you need to "tune" the socket before it is used to +connect (for exmaple, to bind it on a given IP address). This parameter +overrides the prepare callback passed to C +and behaves exactly the same way (e.g. it has to provide a +timeout). See the description for the C<$prepare_cb> argument of +C for details. + =item on_header => $callback->($headers) When specified, this callback will be called with the header hash as soon @@ -223,7 +237,10 @@ be extracted, or when the body should be processed incrementally. It is usually preferred over doing your own body handling via -C. +C, but in case of streaming APIs, where HTTP is +only used to create a connection, C is the better +alternative, as it allows you to install your own event handler, reducing +resource usage. =item want_body_handle => $enable @@ -245,7 +262,7 @@ push-style twitter API which starts a JSON/XML stream). If you think you need this, first have a look at C, to see if -that doesn'T solve your problem in a better way. +that doesn't solve your problem in a better way. =back @@ -311,8 +328,8 @@ _slot_schedule $_[0]; } -our $qr_nl = qr<\015?\012>; -our $qr_nlnl = qr<\015?\012\015?\012>; +our $qr_nl = qr{\015?\012}; +our $qr_nlnl = qr{(? 1, sslv2 => 1 }; our $TLS_CTX_HIGH = { cache => 1, verify => 1, verify_peername => "https" }; @@ -357,7 +374,8 @@ my $uhost = $1; $uport = $2 if defined $2; - $hdr{host} = defined $2 ? "$uhost:$2" : "$uhost"; + $hdr{host} = defined $2 ? "$uhost:$2" : "$uhost" + unless exists $hdr{host}; $uhost =~ s/^\[(.*)\]$/$1/; $upath .= "?$query" if length $query; @@ -400,6 +418,8 @@ if ($proxy) { ($rpath, $rhost, $rport, $rscheme) = ($url, @$proxy); + $rscheme = "http" unless defined $rscheme; + # don't support https requests over https-proxy transport, # can't be done with tls as spec'ed, unless you double-encrypt. $rscheme = "http" if $uscheme eq "https" && $rscheme eq "https"; @@ -407,10 +427,12 @@ ($rhost, $rport, $rscheme, $rpath) = ($uhost, $uport, $uscheme, $upath); } - $hdr{"user-agent"} ||= $USERAGENT; - $hdr{referer} ||= "$uscheme://$uauthority$upath"; # leave out fragment and query string, just a heuristic + # leave out fragment and query string, just a heuristic + $hdr{referer} ||= "$uscheme://$uauthority$upath" unless exists $hdr{referer}; + $hdr{"user-agent"} ||= $USERAGENT unless exists $hdr{"user-agent"}; - $hdr{"content-length"} = length $arg{body}; + $hdr{"content-length"} = length $arg{body} + if length $arg{body} || $method ne "GET"; my %state = (connect_guard => 1); @@ -421,7 +443,12 @@ $state{connect_guard} = AnyEvent::Socket::tcp_connect $rhost, $rport, sub { $state{fh} = shift - or return (%state = (), $cb->(undef, { Status => 599, Reason => "$!", URL => $url })); + or do { + my $err = "$!"; + %state = (); + return $cb->(undef, { Status => 599, Reason => $err, URL => $url }); + }; + pop; # free memory, save a tree return unless delete $state{connect_guard}; @@ -464,7 +491,7 @@ # send request $state{handle}->push_write ( "$method $rpath HTTP/1.0\015\012" - . (join "", map "\u$_: $hdr{$_}\015\012", keys %hdr) + . (join "", map "\u$_: $hdr{$_}\015\012", grep defined $hdr{$_}, keys %hdr) . "\015\012" . (delete $arg{body}) ); @@ -485,7 +512,7 @@ # headers, could be optimized a bit $state{handle}->unshift_read (line => $qr_nlnl, sub { - for ("$_[1]\012") { + for ("$_[1]") { y/\015//d; # weed out any \015, as they show up in the weirdest of places. # things seen, not parsed: @@ -592,7 +619,7 @@ } } - if ($redirect) { + if ($redirect && exists $hdr{location}) { # we ignore any errors, as it is very common to receive # Content-Length != 0 but no actual body # we also access %hdr, as $_[1] might be an erro @@ -691,9 +718,7 @@ &$handle_actual_request; } - }, sub { - $timeout - }; + }, $arg{on_prepare} || sub { $timeout }; }; defined wantarray && AnyEvent::Util::guard { %state = () } @@ -724,7 +749,10 @@ =item AnyEvent::HTTP::set_proxy "proxy-url" Sets the default proxy server to use. The proxy-url must begin with a -string of the form C (optionally C). +string of the form C (optionally C), croaks +otherwise. + +To clear an already-set proxy, use C. =item $AnyEvent::HTTP::MAX_RECURSE @@ -737,7 +765,7 @@ =item $AnyEvent::HTTP::MAX_PER_HOST -The maximum number of concurrent conenctions to the same host (identified +The maximum number of concurrent connections to the same host (identified by the hostname). If the limit is exceeded, then the additional requests are queued until previous connections are closed. @@ -755,11 +783,19 @@ =cut sub set_proxy($) { - $PROXY = [$2, $3 || 3128, $1] if $_[0] =~ m%^(https?):// ([^:/]+) (?: : (\d*) )?%ix; + if (length $_[0]) { + $_[0] =~ m%^(https?):// ([^:/]+) (?: : (\d*) )?%ix + or Carp::croak "$_[0]: invalid proxy URL"; + $PROXY = [$2, $3 || 3128, $1] + } else { + undef $PROXY; + } } # initialise proxy from environment -set_proxy $ENV{http_proxy}; +eval { + set_proxy $ENV{http_proxy}; +}; =head1 SEE ALSO