ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent-HTTP/HTTP.pm
(Generate patch)

Comparing AnyEvent-HTTP/HTTP.pm (file contents):
Revision 1.55 by root, Wed Jun 16 19:17:30 2010 UTC vs.
Revision 1.62 by root, Thu Dec 30 04:30:24 2010 UTC

43 43
44use Errno (); 44use Errno ();
45 45
46use AnyEvent 5.0 (); 46use AnyEvent 5.0 ();
47use AnyEvent::Util (); 47use AnyEvent::Util ();
48use AnyEvent::Socket ();
49use AnyEvent::Handle (); 48use AnyEvent::Handle ();
50 49
51use base Exporter::; 50use base Exporter::;
52 51
53our $VERSION = '1.45'; 52our $VERSION = '1.46';
54 53
55our @EXPORT = qw(http_get http_post http_head http_request); 54our @EXPORT = qw(http_get http_post http_head http_request);
56 55
57our $USERAGENT = "Mozilla/5.0 (compatible; U; AnyEvent-HTTP/$VERSION; +http://software.schmorp.de/pkg/AnyEvent)"; 56our $USERAGENT = "Mozilla/5.0 (compatible; U; AnyEvent-HTTP/$VERSION; +http://software.schmorp.de/pkg/AnyEvent)";
58our $MAX_RECURSE = 10; 57our $MAX_RECURSE = 10;
92must be an absolute http or https URL. 91must be an absolute http or https URL.
93 92
94When called in void context, nothing is returned. In other contexts, 93When called in void context, nothing is returned. In other contexts,
95C<http_request> returns a "cancellation guard" - you have to keep the 94C<http_request> returns a "cancellation guard" - you have to keep the
96object at least alive until the callback get called. If the object gets 95object at least alive until the callback get called. If the object gets
97destroyed before the callbakc is called, the request will be cancelled. 96destroyed before the callback is called, the request will be cancelled.
98 97
99The callback will be called with the response body data as first argument 98The callback will be called with the response body data as first argument
100(or C<undef> if an error occured), and a hash-ref with response headers as 99(or C<undef> if an error occured), and a hash-ref with response headers as
101second argument. 100second argument.
102 101
148Whether to recurse requests or not, e.g. on redirects, authentication 147Whether to recurse requests or not, e.g. on redirects, authentication
149retries and so on, and how often to do so. 148retries and so on, and how often to do so.
150 149
151=item headers => hashref 150=item headers => hashref
152 151
153The request headers to use. Currently, C<http_request> may provide its 152The request headers to use, with the header name (I<MUST be in lowercase>)
154own C<Host:>, C<Content-Length:>, C<Connection:> and C<Cookie:> headers 153as key and header value as hash value.
155and will provide defaults for C<User-Agent:> and C<Referer:> (this can be 154
155Currently, http_request> may provide its own C<host>, C<content-length>,
156C<connection> and C<cookie> headers and will provide defaults for
157C<user-agent> and C<referer> (this can be suppressed by using a value of
156suppressed by using C<undef> for these headers in which case they won't be 158C<undef> for these headers in which case they won't be sent at all).
157sent at all).
158 159
159=item timeout => $seconds 160=item timeout => $seconds
160 161
161The time-out to use for various stages - each connect attempt will reset 162The time-out to use for various stages - each connect attempt will reset
162the timeout, as will read or write activity, i.e. this is not an overall 163the timeout, as will read or write activity, i.e. this is not an overall
211connect (for exmaple, to bind it on a given IP address). This parameter 212connect (for exmaple, to bind it on a given IP address). This parameter
212overrides the prepare callback passed to C<AnyEvent::Socket::tcp_connect> 213overrides the prepare callback passed to C<AnyEvent::Socket::tcp_connect>
213and behaves exactly the same way (e.g. it has to provide a 214and behaves exactly the same way (e.g. it has to provide a
214timeout). See the description for the C<$prepare_cb> argument of 215timeout). See the description for the C<$prepare_cb> argument of
215C<AnyEvent::Socket::tcp_connect> for details. 216C<AnyEvent::Socket::tcp_connect> for details.
217
218=item tcp_connect => $callback->($host, $service, $connect_cb, $prepare_cb)
219
220In even rarer cases you want total control over how AnyEvent::HTTP
221establishes connections. Normally it uses L<AnyEvent::Socket::tcp_connect>
222to do this, but you can provide your own C<tcp_connect> function -
223obviously, it has to follow the same calling conventions, except that it
224may always return a connection guard object.
225
226There are probably lots of weird uses for this function, starting from
227tracing the hosts C<http_request> actually tries to connect, to (inexact
228but fast) host => IP address caching or even socks protocol support.
216 229
217=item on_header => $callback->($headers) 230=item on_header => $callback->($headers)
218 231
219When specified, this callback will be called with the header hash as soon 232When specified, this callback will be called with the header hash as soon
220as headers have been successfully received from the remote server (not on 233as headers have been successfully received from the remote server (not on
338 push @{ $CO_SLOT{$_[0]}[1] }, $_[1]; 351 push @{ $CO_SLOT{$_[0]}[1] }, $_[1];
339 352
340 _slot_schedule $_[0]; 353 _slot_schedule $_[0];
341} 354}
342 355
343our $qr_nl = qr{\015?\012};
344our $qr_nlnl = qr{(?<![^\012])\015?\012}; 356our $qr_nlnl = qr{(?<![^\012])\015?\012};
345 357
346our $TLS_CTX_LOW = { cache => 1, sslv2 => 1 }; 358our $TLS_CTX_LOW = { cache => 1, sslv2 => 1 };
347our $TLS_CTX_HIGH = { cache => 1, verify => 1, verify_peername => "https" }; 359our $TLS_CTX_HIGH = { cache => 1, verify => 1, verify_peername => "https" };
348 360
374 386
375 my $proxy = $arg{proxy} || $PROXY; 387 my $proxy = $arg{proxy} || $PROXY;
376 my $timeout = $arg{timeout} || $TIMEOUT; 388 my $timeout = $arg{timeout} || $TIMEOUT;
377 389
378 my ($uscheme, $uauthority, $upath, $query, $fragment) = 390 my ($uscheme, $uauthority, $upath, $query, $fragment) =
379 $url =~ m|(?:([^:/?#]+):)?(?://([^/?#]*))?([^?#]*)(?:\?([^#]*))?(?:#(.*))?|; 391 $url =~ m|(?:([^:/?#]+):)?(?://([^/?#]*))?([^?#]*)(?:(\?[^#]*))?(?:#(.*))?|;
380 392
381 $uscheme = lc $uscheme; 393 $uscheme = lc $uscheme;
382 394
383 my $uport = $uscheme eq "http" ? 80 395 my $uport = $uscheme eq "http" ? 80
384 : $uscheme eq "https" ? 443 396 : $uscheme eq "https" ? 443
392 404
393 $hdr{host} = defined $2 ? "$uhost:$2" : "$uhost" 405 $hdr{host} = defined $2 ? "$uhost:$2" : "$uhost"
394 unless exists $hdr{host}; 406 unless exists $hdr{host};
395 407
396 $uhost =~ s/^\[(.*)\]$/$1/; 408 $uhost =~ s/^\[(.*)\]$/$1/;
397 $upath .= "?$query" if length $query; 409 $upath .= $query if length $query;
398 410
399 $upath =~ s%^/?%/%; 411 $upath =~ s%^/?%/%;
400 412
401 # cookie processing 413 # cookie processing
402 if (my $jar = $arg{cookie_jar}) { 414 if (my $jar = $arg{cookie_jar}) {
455 _get_slot $uhost, sub { 467 _get_slot $uhost, sub {
456 $state{slot_guard} = shift; 468 $state{slot_guard} = shift;
457 469
458 return unless $state{connect_guard}; 470 return unless $state{connect_guard};
459 471
460 $state{connect_guard} = AnyEvent::Socket::tcp_connect $rhost, $rport, sub { 472 my $tcp_connect = $arg{tcp_connect}
473 || do { require AnyEvent::Socket; \&AnyEvent::Socket::tcp_connect };
474
475 $state{connect_guard} = $tcp_connect->(
476 $rhost,
477 $rport,
478 sub {
461 $state{fh} = shift 479 $state{fh} = shift
462 or do { 480 or do {
463 my $err = "$!"; 481 my $err = "$!";
464 %state = (); 482 %state = ();
465 return $cb->(undef, { Status => 599, Reason => $err, @pseudo }); 483 return $cb->(undef, { Status => 599, Reason => $err, @pseudo });
466 }; 484 };
467 485
468 pop; # free memory, save a tree 486 pop; # free memory, save a tree
469 487
470 return unless delete $state{connect_guard}; 488 return unless delete $state{connect_guard};
471 489
472 # get handle 490 # get handle
473 $state{handle} = new AnyEvent::Handle 491 $state{handle} = new AnyEvent::Handle
474 fh => $state{fh}, 492 fh => $state{fh},
493 peername => $rhost,
494 tls_ctx => $arg{tls_ctx},
495 # these need to be reconfigured on keepalive handles
475 timeout => $timeout, 496 timeout => $timeout,
476 peername => $rhost, 497 on_error => sub {
477 tls_ctx => $arg{tls_ctx}; 498 %state = ();
499 $cb->(undef, { Status => 599, Reason => $_[2], @pseudo });
500 },
501 on_eof => sub {
502 %state = ();
503 $cb->(undef, { Status => 599, Reason => "Unexpected end-of-file", @pseudo });
504 },
505 ;
478 506
479 # limit the number of persistent connections 507 # limit the number of persistent connections
480 # keepalive not yet supported 508 # keepalive not yet supported
481 if ($KA_COUNT{$_[1]} < $MAX_PERSISTENT_PER_HOST) { 509# if ($KA_COUNT{$_[1]} < $MAX_PERSISTENT_PER_HOST) {
482 ++$KA_COUNT{$_[1]}; 510# ++$KA_COUNT{$_[1]};
483 $state{handle}{ka_count_guard} = AnyEvent::Util::guard { 511# $state{handle}{ka_count_guard} = AnyEvent::Util::guard {
484 --$KA_COUNT{$_[1]} 512# --$KA_COUNT{$_[1]}
485 }; 513# };
486 $hdr{connection} = "keep-alive"; 514# $hdr{connection} = "keep-alive";
487 } else { 515# } else {
488 delete $hdr{connection}; 516 delete $hdr{connection};
489 } 517# }
490 518
491 # (re-)configure handle
492 $state{handle}->on_error (sub {
493 %state = ();
494 $cb->(undef, { Status => 599, Reason => $_[2], @pseudo });
495 });
496 $state{handle}->on_eof (sub {
497 %state = ();
498 $cb->(undef, { Status => 599, Reason => "Unexpected end-of-file", @pseudo });
499 });
500
501 $state{handle}->starttls ("connect") if $rscheme eq "https"; 519 $state{handle}->starttls ("connect") if $rscheme eq "https";
502 520
503 # handle actual, non-tunneled, request 521 # handle actual, non-tunneled, request
504 my $handle_actual_request = sub { 522 my $handle_actual_request = sub {
505 $state{handle}->starttls ("connect") if $uscheme eq "https" && !exists $state{handle}{tls}; 523 $state{handle}->starttls ("connect") if $uscheme eq "https" && !exists $state{handle}{tls};
506 524
507 # send request 525 # send request
508 $state{handle}->push_write ( 526 $state{handle}->push_write (
509 "$method $rpath HTTP/1.0\015\012" 527 "$method $rpath HTTP/1.0\015\012"
510 . (join "", map "\u$_: $hdr{$_}\015\012", grep defined $hdr{$_}, keys %hdr) 528 . (join "", map "\u$_: $hdr{$_}\015\012", grep defined $hdr{$_}, keys %hdr)
511 . "\015\012" 529 . "\015\012"
512 . (delete $arg{body}) 530 . (delete $arg{body})
513 ); 531 );
514 532
515 # return if error occured during push_write() 533 # return if error occured during push_write()
516 return unless %state; 534 return unless %state;
517 535
518 %hdr = (); # reduce memory usage, save a kitten, also make it possible to re-use 536 %hdr = (); # reduce memory usage, save a kitten, also make it possible to re-use
519 537
520 # status line 538 # status line and headers
521 $state{handle}->push_read (line => $qr_nl, sub {
522 $_[1] =~ /^HTTP\/([0-9\.]+) \s+ ([0-9]{3}) (?: \s+ ([^\015\012]*) )?/ix
523 or return (%state = (), $cb->(undef, { Status => 599, Reason => "Invalid server response ($_[1])", @pseudo }));
524
525 push @pseudo,
526 HTTPVersion => $1,
527 Status => $2,
528 Reason => $3,
529 ;
530
531 # headers, could be optimized a bit
532 $state{handle}->unshift_read (line => $qr_nlnl, sub { 539 $state{handle}->push_read (line => $qr_nlnl, sub {
533 for ("$_[1]") { 540 for ("$_[1]") {
534 y/\015//d; # weed out any \015, as they show up in the weirdest of places. 541 y/\015//d; # weed out any \015, as they show up in the weirdest of places.
542
543 /^HTTP\/([0-9\.]+) \s+ ([0-9]{3}) (?: \s+ ([^\015\012]*) )? \015?\012/igxc
544 or return (%state = (), $cb->(undef, { Status => 599, Reason => "Invalid server response", @pseudo }));
545
546 push @pseudo,
547 HTTPVersion => $1,
548 Status => $2,
549 Reason => $3,
550 ;
535 551
536 # things seen, not parsed: 552 # things seen, not parsed:
537 # p3pP="NON CUR OTPi OUR NOR UNI" 553 # p3pP="NON CUR OTPi OUR NOR UNI"
538 554
539 $hdr{lc $1} .= ",$2" 555 $hdr{lc $1} .= ",$2"
574 my $redirect; 590 my $redirect;
575 591
576 if ($recurse) { 592 if ($recurse) {
577 my $status = $hdr{Status}; 593 my $status = $hdr{Status};
578 594
579 if (($status == 301 || $status == 302) && $method ne "POST") { 595 # industry standard is to redirect POST as GET for
580 # apparently, mozilla et al. just change POST to GET here 596 # 301, 302 and 303, in contrast to http/1.0 and 1.1.
581 # more research is needed before we do the same 597 # also, the UA should ask the user for 301 and 307 and POST,
582 $redirect = 1; 598 # industry standard seems to be to simply follow.
583 } elsif ($status == 303) { 599 # we go with the industry standard.
600 if ($status == 301 or $status == 302 or $status == 303) {
584 # even http/1.1 is unclear on how to mutate the method 601 # HTTP/1.1 is unclear on how to mutate the method
585 $method = "GET" unless $method eq "HEAD"; 602 $method = "GET" unless $method eq "HEAD";
586 $redirect = 1; 603 $redirect = 1;
587 } elsif ($status == 307 && $method =~ /^(?:GET|HEAD)$/) { 604 } elsif ($status == 307) {
588 $redirect = 1; 605 $redirect = 1;
589 } 606 }
590 } 607 }
591 608
592 my $finish = sub { 609 my $finish = sub {
672 } else { 689 } else {
673 # body handling, four different code paths 690 # body handling, four different code paths
674 # for want_body_handle, on_body (2x), normal (2x) 691 # for want_body_handle, on_body (2x), normal (2x)
675 # we might read too much here, but it does not matter yet (no pers. connections) 692 # we might read too much here, but it does not matter yet (no pers. connections)
676 if (!$redirect && $arg{want_body_handle}) { 693 if (!$redirect && $arg{want_body_handle}) {
677 $_[0]->on_eof (undef); 694 $_[0]->on_eof (undef);
678 $_[0]->on_error (undef); 695 $_[0]->on_error (undef);
679 $_[0]->on_read (undef); 696 $_[0]->on_read (undef);
680 697
681 $finish->(delete $state{handle}, \%hdr); 698 $finish->(delete $state{handle}, \%hdr);
682 699
711 $finish->((substr delete $_[0]{rbuf}, 0, $len, ""), \%hdr) 728 $finish->((substr delete $_[0]{rbuf}, 0, $len, ""), \%hdr)
712 if $len <= length $_[0]{rbuf}; 729 if $len <= length $_[0]{rbuf};
713 }); 730 });
714 } else { 731 } else {
715 $_[0]->on_error (sub { 732 $_[0]->on_error (sub {
716 $! == Errno::EPIPE || !$! 733 ($! == Errno::EPIPE || !$!)
717 ? $finish->(delete $_[0]{rbuf}, \%hdr) 734 ? $finish->(delete $_[0]{rbuf}, \%hdr)
718 : $finish->(undef, { Status => 599, Reason => $_[2], @pseudo }); 735 : $finish->(undef, { Status => 599, Reason => $_[2], @pseudo });
719 }); 736 });
720 $_[0]->on_read (sub { }); 737 $_[0]->on_read (sub { });
721 } 738 }
722 } 739 }
723 } 740 }
724 }); 741 });
725 }); 742 };
726 };
727 743
728 # now handle proxy-CONNECT method 744 # now handle proxy-CONNECT method
729 if ($proxy && $uscheme eq "https") { 745 if ($proxy && $uscheme eq "https") {
730 # oh dear, we have to wrap it into a connect request 746 # oh dear, we have to wrap it into a connect request
731 747
732 # maybe re-use $uauthority with patched port? 748 # maybe re-use $uauthority with patched port?
733 $state{handle}->push_write ("CONNECT $uhost:$uport HTTP/1.0\015\012Host: $uhost\015\012\015\012"); 749 $state{handle}->push_write ("CONNECT $uhost:$uport HTTP/1.0\015\012Host: $uhost\015\012\015\012");
734 $state{handle}->push_read (line => $qr_nlnl, sub { 750 $state{handle}->push_read (line => $qr_nlnl, sub {
735 $_[1] =~ /^HTTP\/([0-9\.]+) \s+ ([0-9]{3}) (?: \s+ ([^\015\012]*) )?/ix 751 $_[1] =~ /^HTTP\/([0-9\.]+) \s+ ([0-9]{3}) (?: \s+ ([^\015\012]*) )?/ix
736 or return (%state = (), $cb->(undef, { Status => 599, Reason => "Invalid proxy connect response ($_[1])", @pseudo })); 752 or return (%state = (), $cb->(undef, { Status => 599, Reason => "Invalid proxy connect response ($_[1])", @pseudo }));
737 753
738 if ($2 == 200) { 754 if ($2 == 200) {
739 $rpath = $upath; 755 $rpath = $upath;
740 &$handle_actual_request; 756 &$handle_actual_request;
741 } else { 757 } else {
742 %state = (); 758 %state = ();
743 $cb->(undef, { Status => $2, Reason => $3, @pseudo }); 759 $cb->(undef, { Status => $2, Reason => $3, @pseudo });
760 }
744 } 761 });
745 });
746 } else { 762 } else {
747 &$handle_actual_request; 763 &$handle_actual_request;
764 }
765
748 } 766 },
749
750 }, $arg{on_prepare} || sub { $timeout }; 767 $arg{on_prepare} || sub { $timeout }
768 );
751 }; 769 };
752 770
753 defined wantarray && AnyEvent::Util::guard { %state = () } 771 defined wantarray && AnyEvent::Util::guard { %state = () }
754} 772}
755 773
790string of the form C<http://host:port> (optionally C<https:...>), croaks 808string of the form C<http://host:port> (optionally C<https:...>), croaks
791otherwise. 809otherwise.
792 810
793To clear an already-set proxy, use C<undef>. 811To clear an already-set proxy, use C<undef>.
794 812
813=item $date = AnyEvent::HTTP::format_date $timestamp
814
815Takes a POSIX timestamp (seconds since the epoch) and formats it as a HTTP
816Date (RFC 2616).
817
818=item $timestamp = AnyEvent::HTTP::parse_date $date
819
820Takes a HTTP Date (RFC 2616) and returns the corresponding POSIX
821timestamp, or C<undef> if the date cannot be parsed.
822
795=item $AnyEvent::HTTP::MAX_RECURSE 823=item $AnyEvent::HTTP::MAX_RECURSE
796 824
797The default value for the C<recurse> request parameter (default: C<10>). 825The default value for the C<recurse> request parameter (default: C<10>).
798 826
799=item $AnyEvent::HTTP::USERAGENT 827=item $AnyEvent::HTTP::USERAGENT
817connections. This number of can be useful for load-leveling. 845connections. This number of can be useful for load-leveling.
818 846
819=back 847=back
820 848
821=cut 849=cut
850
851our @month = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
852our @weekday = qw(Sun Mon Tue Wed Thu Fri Sat);
853
854sub format_date($) {
855 my ($time) = @_;
856
857 # RFC 822/1123 format
858 my ($S, $M, $H, $mday, $mon, $year, $wday, $yday, undef) = gmtime $time;
859
860 sprintf "%s, %02d %s %04d %02d:%02d:%02d GMT",
861 $weekday[$wday], $mday, $month[$mon], $year + 1900,
862 $H, $M, $S;
863}
864
865sub parse_date($) {
866 my ($date) = @_;
867
868 my ($d, $m, $y, $H, $M, $S);
869
870 if ($date =~ /^[A-Z][a-z][a-z], ([0-9][0-9]) ([A-Z][a-z][a-z]) ([0-9][0-9][0-9][0-9]) ([0-9][0-9]):([0-9][0-9]):([0-9][0-9]) GMT$/) {
871 # RFC 822/1123, required by RFC 2616
872 ($d, $m, $y, $H, $M, $S) = ($1, $2, $3, $4, $5, $6);
873
874 } elsif ($date =~ /^[A-Z][a-z]+, ([0-9][0-9])-([A-Z][a-z][a-z])-([0-9][0-9]) ([0-9][0-9]):([0-9][0-9]):([0-9][0-9]) GMT$/) {
875 # RFC 850
876 ($d, $m, $y, $H, $M, $S) = ($1, $2, $3 < 69 ? $3 + 2000 : $3 + 1900, $4, $5, $6);
877
878 } elsif ($date =~ /^[A-Z][a-z][a-z] ([A-Z][a-z][a-z]) ([0-9 ][0-9]) ([0-9][0-9]):([0-9][0-9]):([0-9][0-9]) ([0-9][0-9][0-9][0-9])$/) {
879 # ISO C's asctime
880 ($d, $m, $y, $H, $M, $S) = ($2, $1, $6, $3, $4, $5);
881 }
882 # other formats fail in the loop below
883
884 for (0..11) {
885 if ($m eq $month[$_]) {
886 require Time::Local;
887 return Time::Local::timegm ($S, $M, $H, $d, $_, $y);
888 }
889 }
890
891 undef
892}
822 893
823sub set_proxy($) { 894sub set_proxy($) {
824 if (length $_[0]) { 895 if (length $_[0]) {
825 $_[0] =~ m%^(https?):// ([^:/]+) (?: : (\d*) )?%ix 896 $_[0] =~ m%^(https?):// ([^:/]+) (?: : (\d*) )?%ix
826 or Carp::croak "$_[0]: invalid proxy URL"; 897 or Carp::croak "$_[0]: invalid proxy URL";
833# initialise proxy from environment 904# initialise proxy from environment
834eval { 905eval {
835 set_proxy $ENV{http_proxy}; 906 set_proxy $ENV{http_proxy};
836}; 907};
837 908
909=head2 SOCKS PROXIES
910
911Socks proxies are not directly supported by AnyEvent::HTTP. You can
912compile your perl to support socks, or use an external program such as
913F<socksify> (dante) or F<tsocks> to make your program use a socks proxy
914transparently.
915
916Alternatively, for AnyEvent::HTTP only, you can use your own
917C<tcp_connect> function that does the proxy handshake - here is an example
918that works with socks4a proxies:
919
920 use Errno;
921 use AnyEvent::Util;
922 use AnyEvent::Socket;
923 use AnyEvent::Handle;
924
925 # host, port and username of/for your socks4a proxy
926 my $socks_host = "10.0.0.23";
927 my $socks_port = 9050;
928 my $socks_user = "";
929
930 sub socks4a_connect {
931 my ($host, $port, $connect_cb, $prepare_cb) = @_;
932
933 my $hdl = new AnyEvent::Handle
934 connect => [$socks_host, $socks_port],
935 on_prepare => sub { $prepare_cb->($_[0]{fh}) },
936 on_error => sub { $connect_cb->() },
937 ;
938
939 $hdl->push_write (pack "CCnNZ*Z*", 4, 1, $port, 1, $socks_user, $host);
940
941 $hdl->push_read (chunk => 8, sub {
942 my ($hdl, $chunk) = @_;
943 my ($status, $port, $ipn) = unpack "xCna4", $chunk;
944
945 if ($status == 0x5a) {
946 $connect_cb->($hdl->{fh}, (format_address $ipn) . ":$port");
947 } else {
948 $! = Errno::ENXIO; $connect_cb->();
949 }
950 });
951
952 $hdl
953 }
954
955Use C<socks4a_connect> instead of C<tcp_connect> when doing C<http_request>s,
956possibly after switching off other proxy types:
957
958 AnyEvent::HTTP::set_proxy undef; # usually you do not want other proxies
959
960 http_get 'http://www.google.com', tcp_connect => \&socks4a_connect, sub {
961 my ($data, $headers) = @_;
962 ...
963 };
964
838=head1 SEE ALSO 965=head1 SEE ALSO
839 966
840L<AnyEvent>. 967L<AnyEvent>.
841 968
842=head1 AUTHOR 969=head1 AUTHOR

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines