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.124 by root, Fri May 8 21:26:16 2015 UTC vs.
Revision 1.132 by root, Thu Aug 30 17:05:45 2018 UTC

46use AnyEvent::Util (); 46use AnyEvent::Util ();
47use AnyEvent::Handle (); 47use AnyEvent::Handle ();
48 48
49use base Exporter::; 49use base Exporter::;
50 50
51our $VERSION = 2.21; 51our $VERSION = 2.24;
52 52
53our @EXPORT = qw(http_get http_post http_head http_request); 53our @EXPORT = qw(http_get http_post http_head http_request);
54 54
55our $USERAGENT = "Mozilla/5.0 (compatible; U; AnyEvent-HTTP/$VERSION; +http://software.schmorp.de/pkg/AnyEvent)"; 55our $USERAGENT = "Mozilla/5.0 (compatible; U; AnyEvent-HTTP/$VERSION; +http://software.schmorp.de/pkg/AnyEvent)";
56our $MAX_RECURSE = 10; 56our $MAX_RECURSE = 10;
454 454
455# expire cookies 455# expire cookies
456sub cookie_jar_expire($;$) { 456sub cookie_jar_expire($;$) {
457 my ($jar, $session_end) = @_; 457 my ($jar, $session_end) = @_;
458 458
459 %$jar = () if $jar->{version} != 1; 459 %$jar = () if $jar->{version} != 2;
460 460
461 my $anow = AE::now; 461 my $anow = AE::now;
462 462
463 while (my ($chost, $paths) = each %$jar) { 463 while (my ($chost, $paths) = each %$jar) {
464 next unless ref $paths; 464 next unless ref $paths;
484 484
485# extract cookies from jar 485# extract cookies from jar
486sub cookie_jar_extract($$$$) { 486sub cookie_jar_extract($$$$) {
487 my ($jar, $scheme, $host, $path) = @_; 487 my ($jar, $scheme, $host, $path) = @_;
488 488
489 %$jar = () if $jar->{version} != 1; 489 %$jar = () if $jar->{version} != 2;
490
491 $host = AnyEvent::Util::idn_to_ascii $host
492 if $host =~ /[^\x00-\x7f]/;
490 493
491 my @cookies; 494 my @cookies;
492 495
493 while (my ($chost, $paths) = each %$jar) { 496 while (my ($chost, $paths) = each %$jar) {
494 next unless ref $paths; 497 next unless ref $paths;
495 498
496 if ($chost =~ /^\./) { 499 # exact match or suffix including . match
497 next unless $chost eq substr $host, -length $chost; 500 $chost eq $host or ".$chost" eq substr $host, -1 - length $chost
498 } elsif ($chost =~ /\./) {
499 next unless $chost eq $host;
500 } else {
501 next; 501 or next;
502 }
503 502
504 while (my ($cpath, $cookies) = each %$paths) { 503 while (my ($cpath, $cookies) = each %$paths) {
505 next unless $cpath eq substr $path, 0, length $cpath; 504 next unless $cpath eq substr $path, 0, length $cpath;
506 505
507 while (my ($cookie, $kv) = each %$cookies) { 506 while (my ($cookie, $kv) = each %$cookies) {
528} 527}
529 528
530# parse set_cookie header into jar 529# parse set_cookie header into jar
531sub cookie_jar_set_cookie($$$$) { 530sub cookie_jar_set_cookie($$$$) {
532 my ($jar, $set_cookie, $host, $date) = @_; 531 my ($jar, $set_cookie, $host, $date) = @_;
532
533 %$jar = () if $jar->{version} != 2;
533 534
534 my $anow = int AE::now; 535 my $anow = int AE::now;
535 my $snow; # server-now 536 my $snow; # server-now
536 537
537 for ($set_cookie) { 538 for ($set_cookie) {
583 584
584 my $cdom; 585 my $cdom;
585 my $cpath = (delete $kv{path}) || "/"; 586 my $cpath = (delete $kv{path}) || "/";
586 587
587 if (exists $kv{domain}) { 588 if (exists $kv{domain}) {
588 $cdom = delete $kv{domain}; 589 $cdom = $kv{domain};
589 590
590 $cdom =~ s/^\.?/./; # make sure it starts with a "." 591 $cdom =~ s/^\.?/./; # make sure it starts with a "."
591 592
592 next if $cdom =~ /\.$/; 593 next if $cdom =~ /\.$/;
593 594
594 # this is not rfc-like and not netscape-like. go figure. 595 # this is not rfc-like and not netscape-like. go figure.
595 my $ndots = $cdom =~ y/.//; 596 my $ndots = $cdom =~ y/.//;
596 next if $ndots < ($cdom =~ /\.[^.][^.]\.[^.][^.]$/ ? 3 : 2); 597 next if $ndots < ($cdom =~ /\.[^.][^.]\.[^.][^.]$/ ? 3 : 2);
598
599 $cdom = substr $cdom, 1; # remove initial .
597 } else { 600 } else {
598 $cdom = $host; 601 $cdom = $host;
599 } 602 }
600 603
601 # store it 604 # store it
602 $jar->{version} = 1; 605 $jar->{version} = 2;
603 $jar->{lc $cdom}{$cpath}{$name} = \%kv; 606 $jar->{lc $cdom}{$cpath}{$name} = \%kv;
604 607
605 redo if /\G\s*,/gc; 608 redo if /\G\s*,/gc;
606 } 609 }
607} 610}
895 # we give our best and fall back to URI if available. 898 # we give our best and fall back to URI if available.
896 if (exists $hdr{location}) { 899 if (exists $hdr{location}) {
897 my $loc = $hdr{location}; 900 my $loc = $hdr{location};
898 901
899 if ($loc =~ m%^//%) { # // 902 if ($loc =~ m%^//%) { # //
900 $loc = "$rscheme:$loc"; 903 $loc = "$uscheme:$loc";
901 904
902 } elsif ($loc eq "") { 905 } elsif ($loc eq "") {
903 $loc = $url; 906 $loc = $url;
904 907
905 } elsif ($loc !~ /^(?: $ | [^:\/?\#]+ : )/x) { # anything "simple" 908 } elsif ($loc !~ /^(?: $ | [^:\/?\#]+ : )/x) { # anything "simple"
906 $loc =~ s/^\.\/+//; 909 $loc =~ s/^\.\/+//;
907 910
908 if ($loc !~ m%^[.?#]%) { 911 if ($loc !~ m%^[.?#]%) {
909 my $prefix = "$rscheme://$uhost:$uport"; 912 my $prefix = "$uscheme://$uauthority";
910 913
911 unless ($loc =~ s/^\///) { 914 unless ($loc =~ s/^\///) {
912 $prefix .= $upath; 915 $prefix .= $upath;
913 $prefix =~ s/\/[^\/]*$//; 916 $prefix =~ s/\/[^\/]*$//;
914 } 917 }
1031 $finish->(delete $state{handle}); 1034 $finish->(delete $state{handle});
1032 1035
1033 } elsif ($chunked) { 1036 } elsif ($chunked) {
1034 my $cl = 0; 1037 my $cl = 0;
1035 my $body = ""; 1038 my $body = "";
1036 my $on_body = $arg{on_body} || sub { $body .= shift; 1 }; 1039 my $on_body = (!$redirect && $arg{on_body}) || sub { $body .= shift; 1 };
1037 1040
1038 $state{read_chunk} = sub { 1041 $state{read_chunk} = sub {
1039 $_[1] =~ /^([0-9a-fA-F]+)/ 1042 $_[1] =~ /^([0-9a-fA-F]+)/
1040 or return $finish->(undef, $ae_error => "Garbled chunked transfer encoding"); 1043 or return $finish->(undef, $ae_error => "Garbled chunked transfer encoding");
1041 1044
1074 } 1077 }
1075 }; 1078 };
1076 1079
1077 $_[0]->push_read (line => $state{read_chunk}); 1080 $_[0]->push_read (line => $state{read_chunk});
1078 1081
1079 } elsif ($arg{on_body}) { 1082 } elsif (!$redirect && $arg{on_body}) {
1080 if (defined $len) { 1083 if (defined $len) {
1081 $_[0]->on_read (sub { 1084 $_[0]->on_read (sub {
1082 $len -= length $_[0]{rbuf}; 1085 $len -= length $_[0]{rbuf};
1083 1086
1084 $arg{on_body}(delete $_[0]{rbuf}, \%hdr) 1087 $arg{on_body}(delete $_[0]{rbuf}, \%hdr)
1217 # on a keepalive request (in theory, this should be a separate config option). 1220 # on a keepalive request (in theory, this should be a separate config option).
1218 if ($persistent && $KA_CACHE{$ka_key}) { 1221 if ($persistent && $KA_CACHE{$ka_key}) {
1219 $was_persistent = 1; 1222 $was_persistent = 1;
1220 1223
1221 $state{handle} = ka_fetch $ka_key; 1224 $state{handle} = ka_fetch $ka_key;
1222 $state{handle}->destroyed 1225# $state{handle}->destroyed
1223 and die "AnyEvent::HTTP: unexpectedly got a destructed handle (1), please report.";#d# 1226# and die "AnyEvent::HTTP: unexpectedly got a destructed handle (1), please report.";#d#
1224 $prepare_handle->(); 1227 $prepare_handle->();
1225 $state{handle}->destroyed 1228# $state{handle}->destroyed
1226 and die "AnyEvent::HTTP: unexpectedly got a destructed handle (2), please report.";#d# 1229# and die "AnyEvent::HTTP: unexpectedly got a destructed handle (2), please report.";#d#
1227 $handle_actual_request->(); 1230 $handle_actual_request->();
1228 1231
1229 } else { 1232 } else {
1230 my $tcp_connect = $arg{tcp_connect} 1233 my $tcp_connect = $arg{tcp_connect}
1231 || do { require AnyEvent::Socket; \&AnyEvent::Socket::tcp_connect }; 1234 || do { require AnyEvent::Socket; \&AnyEvent::Socket::tcp_connect };
1291function from time to time. 1294function from time to time.
1292 1295
1293A cookie jar is initially an empty hash-reference that is managed by this 1296A cookie jar is initially an empty hash-reference that is managed by this
1294module. Its format is subject to change, but currently it is as follows: 1297module. Its format is subject to change, but currently it is as follows:
1295 1298
1296The key C<version> has to contain C<1>, otherwise the hash gets 1299The key C<version> has to contain C<2>, otherwise the hash gets
1297emptied. All other keys are hostnames or IP addresses pointing to 1300cleared. All other keys are hostnames or IP addresses pointing to
1298hash-references. The key for these inner hash references is the 1301hash-references. The key for these inner hash references is the
1299server path for which this cookie is meant, and the values are again 1302server path for which this cookie is meant, and the values are again
1300hash-references. Each key of those hash-references is a cookie name, and 1303hash-references. Each key of those hash-references is a cookie name, and
1301the value, you guessed it, is another hash-reference, this time with the 1304the value, you guessed it, is another hash-reference, this time with the
1302key-value pairs from the cookie, except for C<expires> and C<max-age>, 1305key-value pairs from the cookie, except for C<expires> and C<max-age>,
1306 1309
1307Here is an example of a cookie jar with a single cookie, so you have a 1310Here is an example of a cookie jar with a single cookie, so you have a
1308chance of understanding the above paragraph: 1311chance of understanding the above paragraph:
1309 1312
1310 { 1313 {
1311 version => 1, 1314 version => 2,
1312 "10.0.0.1" => { 1315 "10.0.0.1" => {
1313 "/" => { 1316 "/" => {
1314 "mythweb_id" => { 1317 "mythweb_id" => {
1315 _expires => 1293917923, 1318 _expires => 1293917923,
1316 value => "ooRung9dThee3ooyXooM1Ohm", 1319 value => "ooRung9dThee3ooyXooM1Ohm",
1461 or die "$file: $!"; 1464 or die "$file: $!";
1462 1465
1463 my %hdr; 1466 my %hdr;
1464 my $ofs = 0; 1467 my $ofs = 0;
1465 1468
1466 warn stat $fh;
1467 warn -s _;
1468 if (stat $fh and -s _) { 1469 if (stat $fh and -s _) {
1469 $ofs = -s _; 1470 $ofs = -s _;
1470 warn "-s is ", $ofs; 1471 warn "-s is ", $ofs;
1471 $hdr{"if-unmodified-since"} = AnyEvent::HTTP::format_date +(stat _)[9]; 1472 $hdr{"if-unmodified-since"} = AnyEvent::HTTP::format_date +(stat _)[9];
1472 $hdr{"range"} = "bytes=$ofs-"; 1473 $hdr{"range"} = "bytes=$ofs-";
1500 my (undef, $hdr) = @_; 1501 my (undef, $hdr) = @_;
1501 1502
1502 my $status = $hdr->{Status}; 1503 my $status = $hdr->{Status};
1503 1504
1504 if (my $time = AnyEvent::HTTP::parse_date $hdr->{"last-modified"}) { 1505 if (my $time = AnyEvent::HTTP::parse_date $hdr->{"last-modified"}) {
1505 utime $fh, $time, $time; 1506 utime $time, $time, $fh;
1506 } 1507 }
1507 1508
1508 if ($status == 200 || $status == 206 || $status == 416) { 1509 if ($status == 200 || $status == 206 || $status == 416) {
1509 # download ok || resume ok || file already fully downloaded 1510 # download ok || resume ok || file already fully downloaded
1510 $cb->(1, $hdr); 1511 $cb->(1, $hdr);

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines