File Coverage

blib/lib/AnyEvent/Connector.pm
Criterion Covered Total %
statement 77 80 96.2
branch 25 28 89.2
condition 1 3 33.3
subroutine 15 15 100.0
pod 3 3 100.0
total 121 129 93.8


line stmt bran cond sub pod time code
1             package AnyEvent::Connector;
2 4     4   621197 use strict;
  4         9  
  4         168  
3 4     4   23 use warnings;
  4         16  
  4         305  
4 4     4   28 use Carp qw(croak);
  4         11  
  4         225  
5 4     4   2407 use AnyEvent::Socket ();
  4         147813  
  4         195  
6 4     4   3004 use URI;
  4         36391  
  4         170  
7              
8 4     4   2163 use AnyEvent::Connector::Proxy::http;
  4         14  
  4         4074  
9              
10              
11             our $VERSION = "0.04";
12              
13             sub new {
14 19     19 1 749961 my ($class, %args) = @_;
15 19         107 my $self = bless {
16             proxy_obj => undef,
17             no_proxy => []
18             }, $class;
19 19         112 $self->_env_proxy_for($args{env_proxy});
20 19         57 my $proxy = $args{proxy};
21 19 100       61 if(defined($proxy)) {
22 14         55 $self->_set_proxy($proxy);
23             }
24 19         59 my $no_proxy = $args{no_proxy};
25 19 100       80 if(defined($no_proxy)) {
26 8         52 $self->_set_no_proxy($no_proxy);
27             }
28 19         81 return $self;
29             }
30              
31             sub _set_proxy {
32 20     20   56 my ($self, $proxy) = @_;
33 20 100       69 if($proxy eq "") {
34 1         7 $self->{proxy_obj} = undef;
35 1         3 return;
36             }
37 19         210 my $proxy_uri = URI->new($proxy);
38 19         39257 my $scheme = $proxy_uri->scheme;
39 19 50 33     901 if(!defined($scheme) || $scheme ne "http") {
40 0         0 croak "Only http proxy is supported: $proxy";
41             }
42 19         154 $self->{proxy_obj} = AnyEvent::Connector::Proxy::http->new($proxy_uri);
43             }
44              
45             sub _set_no_proxy {
46 14     14   35 my ($self, $no_proxy) = @_;
47 14         37 my $ref = ref($no_proxy);
48 14 100       52 if($ref eq "ARRAY") {
    50          
49             ;
50             }elsif(!$ref) {
51 6         16 $no_proxy = [$no_proxy];
52             }else {
53 0         0 croak "no_proxy expects STRING or ARRAYREF, but it was $ref";
54             }
55 14         39 $self->{no_proxy} = [grep {$_ ne ""} @$no_proxy];
  14         70  
56             }
57              
58             sub _env_proxy_for {
59 19     19   62 my ($self, $protocol) = @_;
60 19 100       82 return if !defined($protocol);
61 7         25 $self->_env_no_proxy();
62 7         33 my @keys = (lc($protocol) . "_proxy", uc($protocol) . "_PROXY");
63 7         18 foreach my $key (@keys) {
64 8         18 my $p = $ENV{$key};
65 8 100       29 if(defined($p)) {
66 6         22 $self->_set_proxy($p);
67 6         22 return;
68             }
69             }
70             }
71              
72             sub _env_no_proxy {
73 7     7   15 my ($self) = @_;
74 7         18 foreach my $key (qw(no_proxy NO_PROXY)) {
75 8         23 my $no_proxy = $ENV{$key};
76 8 100       37 if(defined($no_proxy)) {
77 6         39 $self->_set_no_proxy([split /\s*,\s*/, $no_proxy]);
78 6         18 return;
79             }
80             }
81             }
82              
83             sub _proxy_uri_for {
84 55     55   143 my ($self, $host, $port) = @_;
85 55         94 foreach my $no_domain (@{$self->{no_proxy}}) {
  55         165  
86 33 100       467 if($host =~ /\Q$no_domain\E$/) {
87 12         42 return undef;
88             }
89             }
90 43         131 return $self->{proxy_obj};
91             }
92              
93             sub proxy_for {
94 51     51 1 28753 my ($self, $host, $port) = @_;
95 51         153 my $p = $self->_proxy_uri_for($host, $port);
96 51 100       293 return defined($p) ? $p->uri_string : undef;
97             }
98              
99             sub tcp_connect {
100 4     4 1 305 my ($self, $host, $port, $connect_cb, $prepare_cb) = @_;
101 4         16 my $proxy = $self->_proxy_uri_for($host, $port);
102 4 50       14 if(!defined($proxy)) {
103 0         0 return AnyEvent::Socket::tcp_connect $host, $port, $connect_cb, $prepare_cb;
104             }
105             return AnyEvent::Socket::tcp_connect $proxy->host, $proxy->port, sub {
106 4     4   3119 my ($fh, $conn_host, $conn_port, $retry) = @_;
107 4 100       18 if(!defined($fh)) {
108 1         5 $connect_cb->();
109 1         34 return;
110             }
111             $proxy->establish_proxy($fh, $host, $port, sub {
112 3         9 my ($success) = @_;
113 3 100       20 $connect_cb->($success ? ($fh, $conn_host, $conn_port, $retry) : ());
114 3         31 });
115 4         22 }, $prepare_cb;
116             }
117              
118             1;
119             __END__