AnyEvent-Connector-0.04000755001750001750 014522373624 15123 5ustar00toshiotoshio000000000000AnyEvent-Connector-0.04/Build.PL000444001750001750 227514522373624 16562 0ustar00toshiotoshio000000000000use 5.006; use strict; use warnings; use Module::Build; use Module::Build::Prereqs::FromCPANfile; Module::Build->new( module_name => 'AnyEvent::Connector', license => 'perl', dist_author => q{Toshio Ito }, dist_version_from => 'lib/AnyEvent/Connector.pm', release_status => 'stable', add_to_cleanup => [ 'AnyEvent-Connector-*' ], recursive_test_files => 1, dynamic_config => 1, (-d "share") ? (share_dir => "share") : (), mb_prereqs_from_cpanfile(), no_index => { directory => ["t", "xt", "eg", "inc", "share"], file => ['README.pod', 'README.md'], }, meta_add => { 'meta-spec' => { version => 2, url => 'https://metacpan.org/pod/CPAN::Meta::Spec', }, resources => { bugtracker => { web => 'https://github.com/debug-ito/AnyEvent-Connector/issues', }, repository => { url => 'git://github.com/debug-ito/AnyEvent-Connector.git', web => 'https://github.com/debug-ito/AnyEvent-Connector', }, } } )->create_build_script(); AnyEvent-Connector-0.04/Changes000444001750001750 66714522373624 16544 0ustar00toshiotoshio000000000000Revision history for AnyEvent-Connector 0.04 2023-11-07 [Bug fix] fix probable memory leak (gh#2) 0.03 2018-04-02 [Bug fix] fix exception (warning) when the proxy responds with non-2XX HTTP status. 0.02 2018-03-28 [Bug fix] fix no_proxy env is loaded even if env_proxy option is not specified (gh#1) 0.01 2018-03-26 First version, released on an unsuspecting world. AnyEvent-Connector-0.04/MANIFEST000444001750001750 34714522373624 16375 0ustar00toshiotoshio000000000000Build.PL Changes cpanfile lib/AnyEvent/Connector.pm lib/AnyEvent/Connector/Proxy/http.pm MANIFEST This list of files README t/00-load.t t/connect.t t/env_proxy.t t/proxy_for.t xt/https.t xt/manifest.t xt/pod.t META.yml META.json AnyEvent-Connector-0.04/META.json000444001750001750 305114522373624 16700 0ustar00toshiotoshio000000000000{ "abstract" : "tcp_connect with transparent proxy handling", "author" : [ "Toshio Ito " ], "dynamic_config" : 1, "generated_by" : "Module::Build version 0.4231", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "AnyEvent-Connector", "no_index" : { "directory" : [ "t", "xt", "eg", "inc", "share" ], "file" : [ "README.pod", "README.md" ] }, "prereqs" : { "configure" : { "requires" : { "Module::Build" : "0.42", "Module::Build::Prereqs::FromCPANfile" : "0.02" } }, "runtime" : { "requires" : { "AnyEvent::Handle" : "0", "AnyEvent::Socket" : "0", "URI" : "0" } }, "test" : { "requires" : { "AnyEvent::Handle" : "0", "AnyEvent::Socket" : "0", "Net::EmptyPort" : "0", "Test::More" : "0" } } }, "release_status" : "stable", "resources" : { "bugtracker" : { "web" : "https://github.com/debug-ito/AnyEvent-Connector/issues" }, "repository" : { "type" : "git", "url" : "git://github.com/debug-ito/AnyEvent-Connector.git", "web" : "https://github.com/debug-ito/AnyEvent-Connector" } }, "version" : "0.04", "x_serialization_backend" : "JSON::PP version 4.06" } AnyEvent-Connector-0.04/META.yml000444001750001750 164514522373624 16537 0ustar00toshiotoshio000000000000--- abstract: 'tcp_connect with transparent proxy handling' author: - 'Toshio Ito ' build_requires: AnyEvent::Handle: '0' AnyEvent::Socket: '0' Net::EmptyPort: '0' Test::More: '0' configure_requires: Module::Build: '0.42' Module::Build::Prereqs::FromCPANfile: '0.02' dynamic_config: 1 generated_by: 'Module::Build version 0.4231, CPAN::Meta::Converter version 2.150010' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: '1.4' name: AnyEvent-Connector no_index: directory: - t - xt - eg - inc - share file: - README.pod - README.md requires: AnyEvent::Handle: '0' AnyEvent::Socket: '0' URI: '0' resources: bugtracker: https://github.com/debug-ito/AnyEvent-Connector/issues repository: git://github.com/debug-ito/AnyEvent-Connector.git version: '0.04' x_serialization_backend: 'CPAN::Meta::YAML version 0.018' AnyEvent-Connector-0.04/README000444001750001750 311214522373624 16135 0ustar00toshiotoshio000000000000AnyEvent-Connector The README is used to introduce the module and provide instructions on how to install the module, any machine dependencies it may have (for example C compilers and installed libraries) and any other information that should be provided before the module is installed. A README file is required for CPAN modules since CPAN extracts the README file from a module distribution so that people browsing the archive can use it to get an idea of the module's uses. It is usually a good idea to provide version information here so that people can decide whether fixes for the module are worth downloading. INSTALLATION To install this module, run the following commands: perl Build.PL ./Build ./Build test ./Build install SUPPORT AND DOCUMENTATION After installing, you can find documentation for this module with the perldoc command. perldoc AnyEvent::Connector You can also look for information at: RT, CPAN's request tracker (report bugs here) http://rt.cpan.org/NoAuth/Bugs.html?Dist=AnyEvent-Connector AnnoCPAN, Annotated CPAN documentation http://annocpan.org/dist/AnyEvent-Connector CPAN Ratings http://cpanratings.perl.org/d/AnyEvent-Connector Search CPAN http://search.cpan.org/dist/AnyEvent-Connector/ LICENSE AND COPYRIGHT Copyright (C) 2018 Toshio Ito This program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License. See L for more information. AnyEvent-Connector-0.04/cpanfile000444001750001750 54414522373624 16747 0ustar00toshiotoshio000000000000 requires "AnyEvent::Socket"; requires "AnyEvent::Handle"; requires "URI"; on 'test' => sub { requires 'Test::More' => "0"; requires "Net::EmptyPort"; requires "AnyEvent::Socket"; requires "AnyEvent::Handle"; }; on 'configure' => sub { requires 'Module::Build', '0.42'; requires 'Module::Build::Prereqs::FromCPANfile', "0.02"; }; AnyEvent-Connector-0.04/lib000755001750001750 014522373624 15671 5ustar00toshiotoshio000000000000AnyEvent-Connector-0.04/lib/AnyEvent000755001750001750 014522373624 17422 5ustar00toshiotoshio000000000000AnyEvent-Connector-0.04/lib/AnyEvent/Connector.pm000444001750001750 1705114522373624 22073 0ustar00toshiotoshio000000000000package AnyEvent::Connector; use strict; use warnings; use Carp qw(croak); use AnyEvent::Socket (); use URI; use AnyEvent::Connector::Proxy::http; our $VERSION = "0.04"; sub new { my ($class, %args) = @_; my $self = bless { proxy_obj => undef, no_proxy => [] }, $class; $self->_env_proxy_for($args{env_proxy}); my $proxy = $args{proxy}; if(defined($proxy)) { $self->_set_proxy($proxy); } my $no_proxy = $args{no_proxy}; if(defined($no_proxy)) { $self->_set_no_proxy($no_proxy); } return $self; } sub _set_proxy { my ($self, $proxy) = @_; if($proxy eq "") { $self->{proxy_obj} = undef; return; } my $proxy_uri = URI->new($proxy); my $scheme = $proxy_uri->scheme; if(!defined($scheme) || $scheme ne "http") { croak "Only http proxy is supported: $proxy"; } $self->{proxy_obj} = AnyEvent::Connector::Proxy::http->new($proxy_uri); } sub _set_no_proxy { my ($self, $no_proxy) = @_; my $ref = ref($no_proxy); if($ref eq "ARRAY") { ; }elsif(!$ref) { $no_proxy = [$no_proxy]; }else { croak "no_proxy expects STRING or ARRAYREF, but it was $ref"; } $self->{no_proxy} = [grep {$_ ne ""} @$no_proxy]; } sub _env_proxy_for { my ($self, $protocol) = @_; return if !defined($protocol); $self->_env_no_proxy(); my @keys = (lc($protocol) . "_proxy", uc($protocol) . "_PROXY"); foreach my $key (@keys) { my $p = $ENV{$key}; if(defined($p)) { $self->_set_proxy($p); return; } } } sub _env_no_proxy { my ($self) = @_; foreach my $key (qw(no_proxy NO_PROXY)) { my $no_proxy = $ENV{$key}; if(defined($no_proxy)) { $self->_set_no_proxy([split /\s*,\s*/, $no_proxy]); return; } } } sub _proxy_uri_for { my ($self, $host, $port) = @_; foreach my $no_domain (@{$self->{no_proxy}}) { if($host =~ /\Q$no_domain\E$/) { return undef; } } return $self->{proxy_obj}; } sub proxy_for { my ($self, $host, $port) = @_; my $p = $self->_proxy_uri_for($host, $port); return defined($p) ? $p->uri_string : undef; } sub tcp_connect { my ($self, $host, $port, $connect_cb, $prepare_cb) = @_; my $proxy = $self->_proxy_uri_for($host, $port); if(!defined($proxy)) { return AnyEvent::Socket::tcp_connect $host, $port, $connect_cb, $prepare_cb; } return AnyEvent::Socket::tcp_connect $proxy->host, $proxy->port, sub { my ($fh, $conn_host, $conn_port, $retry) = @_; if(!defined($fh)) { $connect_cb->(); return; } $proxy->establish_proxy($fh, $host, $port, sub { my ($success) = @_; $connect_cb->($success ? ($fh, $conn_host, $conn_port, $retry) : ()); }); }, $prepare_cb; } 1; __END__ =pod =head1 NAME AnyEvent::Connector - tcp_connect with transparent proxy handling =head1 SYNOPSIS use AnyEvent::Connector; ## Specify the proxy setting explicitly. my $c = AnyEvent::Connector->new( proxy => 'http://proxy.example.com:8080', no_proxy => ['localhost', 'your-internal-domain.net'] ); ## Proxy setting from "http_proxy" and "no_proxy" environment variables. my $cenv = AnyEvent::Connector->new( env_proxy => "http", ); ## Same API as AnyEvent::Socket::tcp_connect my $guard = $c->tcp_connect( "target.hogehoge.org", 80, sub { ## connect callback my ($fh ,$host, $port, $retry) = @_; ...; }, sub { ## prepare calback my ($fh) = @_; ...; } ); =head1 DESCRIPTION L object has C method compatible with that from L, and it handles proxy settings transparently. =head1 CLASS METHODS =head2 $conn = AnyEvent::Connector->new(%args) The constructor. Fields in C<%args> are: =over =item C => STR (optional) String of proxy URL. Currently only C proxy is supported. If both C and C are not specified, the C<$conn> will directly connect to the destination host. If both C and C are specified, setting by C is used. Setting empty string to C disables the proxy setting done by C option. =item C => STR or ARRAYREF of STR (optional) String or array-ref of strings of domain names, to which the C<$conn> will directly connect. If both C and C are specified, setting by C is used. Setting empty string or empty array-ref to C disables the no_proxy setting done by C option. =item C => STR (optional) String of protocol specifier. If specified, proxy settings for that protocol are loaded from environment variables, and C<$conn> is created. For example, if C<"http"> is specified, C (or C) and C (or C) environment variables are used to set C and C options, respectively. C and C options have precedence over C option. =back =head1 OBJECT METHOD =head2 $guard = $conn->tcp_connect($host, $port, $connect_cb, $prepare_cb) Make a (possibly proxied) TCP connection to the given C<$host> and C<$port>. If C<< $conn->proxy_for($host, $port) >> returns C, the behavior of this method is exactly the same as C function from L. If C<< $conn->proxy_for($host, $port) >> returns a proxy URL, it behaves in the following way. =over =item * It connects to the proxy, and tells the proxy to connect to the final destination, C<$host> and C<$port>. =item * It runs C<$connect_cb> after the connection to the proxy AND (hopefully) the connection between the proxy and the final destination are both established. $connect_cb->($cb_fh, $cb_host, $cb_port, $cb_retry) C<$cb_fh> is the filehandle to the proxy. C<$cb_host> and C<$cb_port> are the hostname and port of the proxy. =item * If the TCP connection to the proxy is established but the connection to the final destination fails for some reason, C<$connect_cb> is called with no argument passed (just as the original C does). =item * If given, it runs C<$prepare_cb> before it starts connecting to the proxy. =back =head2 $proxy = $conn->proxy_for($host, $port) If C<$conn> uses a proxy to connect to the given C<$host> and C<$port>, it returns the string of the proxy URL. Otherwise, it returns C. =head1 SEE ALSO =over =item * L =item * L - it has C option to implement proxy connection. You can use L for it. =back =head1 REPOSITORY L =head1 BUGS AND FEATURE REQUESTS Please report bugs and feature requests to my Github issues L. Although I prefer Github, non-Github users can use CPAN RT L. Please send email to C to report bugs if you do not have CPAN RT account. =head1 AUTHOR Toshio Ito, C<< >> =head1 LICENSE AND COPYRIGHT Copyright 2018 Toshio Ito. This program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License. See L for more information. =cut AnyEvent-Connector-0.04/lib/AnyEvent/Connector000755001750001750 014522373624 21354 5ustar00toshiotoshio000000000000AnyEvent-Connector-0.04/lib/AnyEvent/Connector/Proxy000755001750001750 014522373624 22475 5ustar00toshiotoshio000000000000AnyEvent-Connector-0.04/lib/AnyEvent/Connector/Proxy/http.pm000444001750001750 367114522373624 24156 0ustar00toshiotoshio000000000000package AnyEvent::Connector::Proxy::http; use strict; use warnings; use AnyEvent::Handle; sub new { my ($class, $uri) = @_; my $self = bless { uri => $uri }, $class; return $self; } sub uri_string { my ($self) = @_; return $self->{uri}->as_string; } sub host { my ($self) = @_; return $self->{uri}->host; } sub port { my ($self) = @_; return $self->{uri}->port; } sub establish_proxy { my ($self, $fh, $target_host, $target_port, $cb) = @_; my $ah; my $header_reader; $ah = AnyEvent::Handle->new( fh => $fh, on_error => sub { ## TODO: how should we report the error detail? undef $ah; undef $header_reader; $cb->(0); }, on_eof => sub { undef $ah; undef $header_reader; $cb->(0); }, ); $ah->push_write( "CONNECT $target_host:$target_port HTTP/1.1\r\n" . "Host: $target_host:$target_port\r\n\r\n" ); $header_reader = sub { my ($h, $line) = @_; if($line eq "") { $ah->destroy(); undef $ah; undef $header_reader; $cb->(1); return; } $ah->push_read(line => $header_reader); }; $ah->push_read(line => sub { my ($h, $line) = @_; if($line !~ qr{^HTTP/1\S* +(\d{3})}) { $ah->destroy(); undef $ah; undef $header_reader; $cb->(0); return; } my $status = $1; if(int($status / 100) != 2) { $ah->destroy(); undef $ah; undef $header_reader; $cb->(0); return; } $ah->push_read(line => $header_reader); }); } 1; __END__ =pod =head1 NAME AnyEvent::Connector::Proxy::http - http Proxy connector =head1 DESCRIPTION This module is internal. End-users should not use it directly. =cut AnyEvent-Connector-0.04/t000755001750001750 014522373624 15366 5ustar00toshiotoshio000000000000AnyEvent-Connector-0.04/t/00-load.t000444001750001750 37414522373624 17030 0ustar00toshiotoshio000000000000use 5.006; use strict; use warnings; use Test::More; plan tests => 2; BEGIN { use_ok('AnyEvent::Connector'); use_ok('AnyEvent::Connector::Proxy::http'); } diag( "Testing AnyEvent::Connector $AnyEvent::Connector::VERSION, Perl $], $^X" ); AnyEvent-Connector-0.04/t/connect.t000444001750001750 1346014522373624 17365 0ustar00toshiotoshio000000000000use strict; use warnings; use Test::More; use Net::EmptyPort qw(empty_port); use AnyEvent::Socket qw(tcp_server); use AnyEvent::Handle; use AnyEvent::Connector; my @warnings; $SIG{__WARN__} = sub { push @warnings, $_[0] }; sub setup_echo_proxy { my $port = empty_port(); my $cv = AnyEvent->condvar; my $proxied_data = ""; my $cb_established = sub { my ($h) = @_; my $got_data = delete $h->{rbuf}; $proxied_data .= $got_data; $h->push_write($got_data); }; my $connect_req = ""; my $cb_receive_conn = sub { my ($h) = @_; $connect_req .= delete $h->{rbuf}; if($connect_req !~ /\r\n\r\n$/) { return; } $h->push_write(qq{HTTP/1.1 200 OK\r\nX-Hoge-Header: hogehoge\r\n\r\n}); $h->on_read($cb_established); }; my @error; my $finish = sub { $cv->send([$connect_req, $proxied_data, \@error]); }; my $server = tcp_server "127.0.0.1", $port, sub { my ($fh) = @_; my $ah; $ah = AnyEvent::Handle->new( fh => $fh, on_error => sub { my ($h, $fatal, $msg) = @_; push @error, [$fatal, $msg]; $ah->destroy(); undef $ah; $finish->(); }, on_eof => sub { $ah->destroy(); undef $ah; $finish->(); }, on_read => $cb_receive_conn ); }; return ($port, $server, $cv); } sub setup_closing_proxy { my $port = empty_port(); my $server = tcp_server '127.0.0.1', $port, sub { my ($fh) = @_; my $ah; $ah = AnyEvent::Handle->new( fh => $fh, on_error => sub { $ah->push_shutdown(); undef $ah; close $fh; undef $fh; }, ); $ah->push_read(line => sub { my ($h) = @_; $h->push_shutdown(); undef $h; close $fh; undef $fh; }); }; return ($port, $server); } sub setup_send_junk_proxy { my ($port) = empty_port(); my $server = tcp_server '127.0.0.1', $port, sub { my ($fh) = @_; my $ah; $ah = AnyEvent::Handle->new( fh => $fh, on_error => sub { undef $ah; close $fh; undef $fh; }, on_read => sub { if($ah->{rbuf} !~ /\r\n\r\n$/) { return; } delete $ah->{rbuf}; $ah->push_write("some junk\r\n"); $ah->push_shutdown(); undef $ah; }, ); }; return ($port, $server); } subtest 'successful echo proxy', sub { my ($proxy_port, $proxy_guard, $proxy_cv) = setup_echo_proxy(); my $conn = AnyEvent::Connector->new( proxy => "http://127.0.0.1:$proxy_port" ); my $client_cv = AnyEvent->condvar; my ($got_host, $got_port); $conn->tcp_connect("this.never.exist.i.guess.com", 5500, sub { (my $fh, $got_host, $got_port) = @_; my $ah; $ah = AnyEvent::Handle->new( fh => $fh, on_error => sub { my ($h, $fatal, $msg) = @_; $ah->destroy(); undef $ah; $client_cv->croak($fatal, $msg); }, on_eof => sub { undef $ah; $client_cv->send(); }, on_read => sub { my ($h) = @_; my $data = delete $h->{rbuf}; $ah->push_shutdown(); $ah->destroy(); undef $ah; $client_cv->send(delete $h->{rbuf}); } ); $ah->push_write("data submitted\n"); $ah->push_read(line => sub { my ($h, $line) = @_; $ah->push_shutdown(); $ah->destroy(); undef $ah; $client_cv->send($line); }); }); my $client_got = $client_cv->recv(); my $proxy_got = $proxy_cv->recv(); is $client_got, "data submitted"; is $got_host, "127.0.0.1"; is $got_port, $proxy_port; is $proxy_got->[0], "CONNECT this.never.exist.i.guess.com:5500 HTTP/1.1\r\nHost: this.never.exist.i.guess.com:5500\r\n\r\n"; is $proxy_got->[1], "data submitted\n"; is_deeply $proxy_got->[2], []; }; subtest "proxy error", sub { my ($proxy_port, $proxy_guard) = setup_closing_proxy(); my $conn = AnyEvent::Connector->new( proxy => "http://127.0.0.1:$proxy_port" ); my $client_cv = AnyEvent->condvar; $conn->tcp_connect("foo.bar.com", 1888, sub { my (@args) = @_; $client_cv->send(\@args); }); my $client_got = $client_cv->recv(); is_deeply $client_got, [], "no arg passed to connect_cb because of proxy error"; }; subtest "proxy not exist", sub { my $no_port = empty_port(); my $conn = AnyEvent::Connector->new( proxy => "http://127.0.0.1:$no_port" ); my $client_cv = AnyEvent->condvar; $conn->tcp_connect("foo.bar.com", 1888, sub { my (@args) = @_; $client_cv->send(\@args); }); my $client_got = $client_cv->recv(); is_deeply $client_got, [], "no arg passed to connect_cb because there is no proxy listening."; }; subtest "proxy sending junk", sub { my ($port, $proxy) = setup_send_junk_proxy(); my $conn = AnyEvent::Connector->new( proxy => "http://127.0.0.1:$port" ); my $client_cv = AnyEvent->condvar; $conn->tcp_connect("foo.bar.com", 12222, sub { my (@args) = @_; $client_cv->send(\@args); }); my $client_got = $client_cv->recv(); is_deeply $client_got, [], "proxy sending junk causes failure."; }; is_deeply \@warnings, [], "no warnings"; done_testing; AnyEvent-Connector-0.04/t/env_proxy.t000444001750001750 450714522373624 17747 0ustar00toshiotoshio000000000000use strict; use warnings; use Test::More; use AnyEvent::Connector; foreach my $e (qw{http_proxy HTTP_PROXY no_proxy NO_PROXY ftp_proxy FTP_PROXY}) { delete $ENV{$e}; } subtest "env_proxy no no_proxy", sub { local $ENV{http_proxy} = "http://foobar.ne.jp:8080"; my $c = AnyEvent::Connector->new( env_proxy => "http" ); is $c->proxy_for("www.foobar.net", 80), "http://foobar.ne.jp:8080"; }; subtest "env_proxy with no_proxy ENV", sub { local $ENV{http_proxy} = "http://foobar.ne.jp:8080"; local $ENV{no_proxy} = "www.foobar.net"; my $c = AnyEvent::Connector->new( env_proxy => "http" ); is $c->proxy_for("www.foobar.net", 80), undef; is $c->proxy_for("backend.foobar.net", 8080), "http://foobar.ne.jp:8080"; }; subtest "env_proxy with proxy override", sub { local $ENV{http_proxy} = "http://foobar.ne.jp:8080"; local $ENV{no_proxy} = "www.foobar.net"; my $c = AnyEvent::Connector->new( env_proxy => "http", proxy => "http://alt.proxy.com:5000" ); is $c->proxy_for("www.foobar.net", 80), undef; is $c->proxy_for("backend.foobar.net", 8080), "http://alt.proxy.com:5000"; $c = AnyEvent::Connector->new( env_proxy => "http", proxy => "", ); is $c->proxy_for("www.foobar.net", 80), undef; is $c->proxy_for("backend.foobar.net", 8080), undef; }; subtest "env_proxy with no_proxy override", sub { local $ENV{http_proxy} = "http://foobar.ne.jp:8080"; local $ENV{no_proxy} = "www.foobar.net"; my $c = AnyEvent::Connector->new( env_proxy => "http", no_proxy => "backend.foobar.net", ); is $c->proxy_for("www.foobar.net", 80), "http://foobar.ne.jp:8080"; is $c->proxy_for("backend.foobar.net", 8080), undef; $c = AnyEvent::Connector->new( env_proxy => "http", no_proxy => "" ); is $c->proxy_for("www.foobar.net", 80), "http://foobar.ne.jp:8080"; is $c->proxy_for("backend.foobar.net", 8080), "http://foobar.ne.jp:8080"; }; subtest "env_proxy with no matching protocol", sub { local $ENV{http_proxy} = "http://foobar.ne.jp:8080"; local $ENV{no_proxy} = "www.foobar.net"; my $c = AnyEvent::Connector->new( env_proxy => "ftp", ); is $c->proxy_for("www.foobar.net", 80), undef; is $c->proxy_for("backend.foobar.net", 8080), undef; }; done_testing; AnyEvent-Connector-0.04/t/proxy_for.t000444001750001750 702414522373624 17742 0ustar00toshiotoshio000000000000use strict; use warnings; use Test::More; use AnyEvent::Connector; subtest "no no_proxy", sub { my $c = AnyEvent::Connector->new( proxy => "http://hoge.com", ); is $c->proxy_for("localhost", 80), "http://hoge.com"; is $c->proxy_for("127.0.0.1", 5000), "http://hoge.com"; is $c->proxy_for("foo.example.com", 22), "http://hoge.com"; is $c->proxy_for("buzz.example.com", 22), "http://hoge.com"; is $c->proxy_for("bar.quux.net",443), "http://hoge.com"; }; subtest "no_proxy domain", sub { my $c = AnyEvent::Connector->new( proxy => "http://hoge.com", no_proxy => "example.com", ); is $c->proxy_for("localhost", 80), "http://hoge.com"; is $c->proxy_for("127.0.0.1", 5000), "http://hoge.com"; is $c->proxy_for("foo.example.com", 22), undef; is $c->proxy_for("buzz.example.com", 22), undef; is $c->proxy_for("bar.quux.net",443), "http://hoge.com"; }; subtest "no_proxy host", sub { my $c = AnyEvent::Connector->new( proxy => "http://hoge.com", no_proxy => "buzz.example.com", ); is $c->proxy_for("localhost", 80), "http://hoge.com"; is $c->proxy_for("127.0.0.1", 5000), "http://hoge.com"; is $c->proxy_for("foo.example.com", 22), "http://hoge.com"; is $c->proxy_for("buzz.example.com", 22), undef; is $c->proxy_for("bar.quux.net",443), "http://hoge.com"; }; subtest "no_proxy list", sub { my $c = AnyEvent::Connector->new( proxy => "http://hoge.com", no_proxy => ["example.com", "localhost"], ); is $c->proxy_for("localhost", 80), undef; is $c->proxy_for("127.0.0.1", 5000), "http://hoge.com"; is $c->proxy_for("foo.example.com", 22), undef; is $c->proxy_for("buzz.example.com", 22), undef; is $c->proxy_for("bar.quux.net",443), "http://hoge.com"; }; subtest "no_proxy IPv4 address", sub { my $c = AnyEvent::Connector->new( proxy => "http://hoge.com", no_proxy => "127.0.0.1", ); is $c->proxy_for("localhost", 80), "http://hoge.com"; is $c->proxy_for("127.0.0.1", 5000), undef; is $c->proxy_for("foo.example.com", 22), "http://hoge.com"; is $c->proxy_for("buzz.example.com", 22), "http://hoge.com"; is $c->proxy_for("bar.quux.net",443), "http://hoge.com"; }; subtest "no_proxy empty string", sub { my $c = AnyEvent::Connector->new( proxy => "http://hoge.com", no_proxy => "", ); is $c->proxy_for("localhost", 80), "http://hoge.com"; is $c->proxy_for("127.0.0.1", 5000), "http://hoge.com"; is $c->proxy_for("foo.example.com", 22), "http://hoge.com"; is $c->proxy_for("buzz.example.com", 22), "http://hoge.com"; is $c->proxy_for("bar.quux.net",443), "http://hoge.com"; }; subtest "no_proxy empty arrayref", sub { my $c = AnyEvent::Connector->new( proxy => "http://hoge.com", no_proxy => [], ); is $c->proxy_for("localhost", 80), "http://hoge.com"; is $c->proxy_for("127.0.0.1", 5000), "http://hoge.com"; is $c->proxy_for("foo.example.com", 22), "http://hoge.com"; is $c->proxy_for("buzz.example.com", 22), "http://hoge.com"; is $c->proxy_for("bar.quux.net",443), "http://hoge.com"; }; subtest "no_proxy environment should be ignored if env_proxy option is not specified", sub { local $ENV{no_proxy} = "foo.com"; my $c = AnyEvent::Connector->new( proxy => "http://bar.net:8080" ); is $c->proxy_for("www.foo.com", 80), "http://bar.net:8080"; is $c->proxy_for("foo.com", 80), "http://bar.net:8080"; is $c->proxy_for("hoge.com", 5000), "http://bar.net:8080"; }; done_testing; AnyEvent-Connector-0.04/xt000755001750001750 014522373624 15556 5ustar00toshiotoshio000000000000AnyEvent-Connector-0.04/xt/https.t000444001750001750 134614522373624 17246 0ustar00toshiotoshio000000000000use strict; use warnings; use Test::More; use AnyEvent; use AnyEvent::Connector; use AnyEvent::HTTP qw(http_get); my $ENV_NAME = "PERL_ANYEVENT_CONNECTOR_TEST_PROXY"; my $proxy_url = $ENV{$ENV_NAME}; if(!defined($proxy_url)) { plan skip_all => "Set $ENV_NAME environment variable to proxy URL."; exit 0; } my $conn = AnyEvent::Connector->new( proxy => $proxy_url ); AnyEvent::HTTP::set_proxy undef; my $cv = AnyEvent->condvar; http_get "https://www.google.com/", tcp_connect => sub { $conn->tcp_connect(@_) }, sub { my ($data, $headers) = @_; $cv->send($data, $headers); }; my ($data, $headers) = $cv->recv; like $headers->{Status}, qr/^2\d\d$/, "successful status"; isnt $data, "", "non-empty data"; done_testing; AnyEvent-Connector-0.04/xt/manifest.t000444001750001750 34514522373624 17670 0ustar00toshiotoshio000000000000use 5.006; use strict; use warnings; use Test::More; use Test::CheckManifest; unless($ENV{RELEASE_TESTING}) { plan(skip_all => "Set RELEASE_TESTING environment variable to test MANIFEST"); } ok_manifest(); done_testing; AnyEvent-Connector-0.04/xt/pod.t000444001750001750 15214522373624 16640 0ustar00toshiotoshio000000000000use 5.006; use strict; use warnings; use Test::More; use Test::Pod; all_pod_files_ok(); done_testing;