File Coverage

blib/lib/LWP/UserAgent/Anonymous.pm
Criterion Covered Total %
statement 26 71 36.6
branch 0 18 0.0
condition 0 12 0.0
subroutine 9 17 52.9
pod 2 3 66.6
total 37 121 30.5


line stmt bran cond sub pod time code
1             package LWP::UserAgent::Anonymous;
2              
3             $LWP::UserAgent::Anonymous::VERSION = '0.09';
4              
5             =head1 NAME
6              
7             LWP::UserAgent::Anonymous - Interface to anonymous LWP::UserAgent.
8              
9             =head1 VERSION
10              
11             Version 0.09
12              
13             =cut
14              
15 1     1   21887 use strict; use warnings;
  1     1   1  
  1         24  
  1         4  
  1         1  
  1         24  
16              
17 1     1   19 use 5.006;
  1         6  
18 1     1   659 use Clone;
  1         3052  
  1         50  
19 1     1   720 use LWP::Simple;
  1         1951315  
  1         14  
20 1     1   2882 use Data::Dumper;
  1         8935  
  1         68  
21 1     1   8 use HTTP::Request;
  1         2  
  1         34  
22 1     1   5 use List::Util qw/shuffle/;
  1         1  
  1         130  
23 1     1   6 use base qw/LWP::UserAgent Clone/;
  1         1  
  1         858  
24              
25             =head1 DESCRIPTION
26              
27             It provides an anonymity to user agent by setting proxy from the pool of proxies
28             fetched from L runtime.
29              
30             =cut
31              
32             $| = 1;
33             our $DEBUG = 0;
34             our $DEFAULT_RETRY_COUNT = 3;
35             our $PROXY_SERVER = 'http://www.gatherproxy.com';
36              
37             =head1 METHODS
38              
39             =head2 anon_request()
40              
41             This is simply acts like proxy handler for user agent. It tries to get hold of a
42             valid proxy server, if it can't then it simply takes the standard route. This
43             method behaves exactly as method request() for LWP::UserAgent plus sets the
44             proxy for you. You may find it takes little longer than usual to respond.
45              
46             use strict; use warnings;
47             use HTTP::Request;
48             use LWP::UserAgent::Anonymous;
49              
50             my $browser = LWP::UserAgent::Anonymous->new;
51             my $request = HTTP::Request->new(GET=>'http://www.google.com/');
52             my $response = $browser->anon_request($request);
53              
54             =cut
55              
56             sub anon_request {
57 0     0 1   my ($self, $request) = @_;
58              
59 0           my $clone = $self->clone();
60 0           my $retry = $DEFAULT_RETRY_COUNT;
61 0           my @proxies = _fetch_proxies();
62              
63 0 0         if (scalar(@proxies)) {
64 0 0         _print("INFO: Max retry: [$retry]") if $DEBUG;
65 0   0       while ($retry > 0 && scalar(@proxies) > 0) {
66 0           my $proxy = shift @proxies;
67 0 0 0       if (defined($proxy) && ($proxy =~ /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,6}/)) {
68 0           $self->proxy(['http','ftp'], sprintf("http://%s/", $proxy));
69 0 0         if ($self->_is_success($proxy)) {
70 0           return $self->SUPER::request($request);
71             }
72             }
73 0           $retry--;
74             }
75             }
76              
77 0 0         _print('WARN: Unable to get the proxy... going no-proxy route now.') if $DEBUG;
78 0           return $clone->SUPER::request($request);
79             }
80              
81             =head2 set_retry()
82              
83             Set retry count when fetching proxies. By default the count is 3.
84              
85             use strict; use warnings;
86             use LWP::UserAgent::Anonymous;
87              
88             my $browser = LWP::UserAgent::Anonymous->new;
89             $browser->set_retry(2);
90              
91             =cut
92              
93             sub set_retry {
94 0     0 1   my ($self, $count) = @_;
95              
96 0           $DEFAULT_RETRY_COUNT = $count;
97             }
98              
99             sub set_debug {
100 0     0 0   my ($self, $value) = @_;
101              
102 0           $DEBUG = $value;
103             }
104              
105             sub _fetch_proxies {
106 0     0     my $proxy = [];
107 0           my $file = get($PROXY_SERVER);
108 0 0         if (defined $file) {
109 0           for my $record (split /\n/,$file) {
110 0           $record =~ s/^\s+//g;
111 0 0         if ($record =~ /^gp\./i) {
112 0 0         if ($record =~ m/\"proxy\_ip\"\:\"(.*?)\".*\"proxy\_port\"\:\"(\d+)\"/i) {
113 0           push @$proxy, sprintf("%s:%d", $1, $2);
114             }
115             }
116             }
117             }
118              
119 0           return shuffle(@$proxy);
120             }
121              
122             sub _is_success {
123 0     0     my ($self, $proxy) = @_;
124              
125 0           my $request = HTTP::Request->new(GET => 'http://www.google.com');
126 0           my $response = $self->SUPER::request($request);
127              
128 0   0       return (defined($response) && $response->is_success);
129             }
130              
131             # Untested code (trying timeout while checking proxy)
132             sub __is_success {
133 0     0     my ($self, $proxy) = @_;
134              
135 0           eval {
136 0     0     local $SIG{ALRM} = sub { die "Timeout" };
  0            
137 0           alarm(20);
138              
139 0           my $request = HTTP::Request->new(GET => 'http://www.google.com');
140 0           my $response = $self->SUPER::request($request);
141              
142 0   0       return (defined($response) && $response->is_success);
143              
144 0           alarm(0);
145             };
146              
147 0 0         return 0 if ($@ =~ /^Timeout/);
148             }
149              
150             sub _print {
151 0     0     my ($message) = @_;
152              
153 0           print {*STDOUT} $message, "\n";
  0            
154             }
155              
156              
157             =head1 AUTHOR
158              
159             Mohammad S Anwar, C<< >>
160              
161             =head1 REPOSITORY
162              
163             L
164              
165             =head1 BUGS
166              
167             Please report any bugs or feature requests to C
168             rt.cpan.org>, or through the web interface at L.
169             I will be notified and then you'll automatically be notified of progress on your
170             bug as I make changes.
171              
172             =head1 SUPPORT
173              
174             You can find documentation for this module with the perldoc command.
175              
176             perldoc LWP::UserAgent::Anonymous
177              
178             You can also look for information at:
179              
180             =over 4
181              
182             =item * RT: CPAN's request tracker
183              
184             L
185              
186             =item * AnnoCPAN: Annotated CPAN documentation
187              
188             L
189              
190             =item * CPAN Ratings
191              
192             L
193              
194             =item * Search CPAN
195              
196             L
197              
198             =back
199              
200             =head1 LICENSE AND COPYRIGHT
201              
202             Copyright (C) 2011 - 2015 Mohammad S Anwar.
203              
204             This program is free software; you can redistribute it and/or modify it under
205             the terms of the the Artistic License (2.0). You may obtain a copy of the full
206             license at:
207              
208             L
209              
210             Any use, modification, and distribution of the Standard or Modified Versions is
211             governed by this Artistic License.By using, modifying or distributing the Package,
212             you accept this license. Do not use, modify, or distribute the Package, if you do
213             not accept this license.
214              
215             If your Modified Version has been derived from a Modified Version made by someone
216             other than you,you are nevertheless required to ensure that your Modified Version
217             complies with the requirements of this license.
218              
219             This license does not grant you the right to use any trademark, service mark,
220             tradename, or logo of the Copyright Holder.
221              
222             This license includes the non-exclusive, worldwide, free-of-charge patent license
223             to make, have made, use, offer to sell, sell, import and otherwise transfer the
224             Package with respect to any patent claims licensable by the Copyright Holder that
225             are necessarily infringed by the Package. If you institute patent litigation
226             (including a cross-claim or counterclaim) against any party alleging that the
227             Package constitutes direct or contributory patent infringement,then this Artistic
228             License to you shall terminate on the date that such litigation is filed.
229              
230             Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND
231             CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED
232             WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
233             NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL LAW. UNLESS
234             REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT,
235             INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE
236             OF THE PACKAGE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
237              
238             =cut
239              
240             1; # End of LWP::UserAgent::Anonymous