File Coverage

blib/lib/LWP/UserAgent/Throttled.pm
Criterion Covered Total %
statement 43 43 100.0
branch 13 16 81.2
condition 3 3 100.0
subroutine 8 8 100.0
pod 3 3 100.0
total 70 73 95.8


line stmt bran cond sub pod time code
1             package LWP::UserAgent::Throttled;
2              
3 4     4   578169 use warnings;
  4         23  
  4         136  
4 4     4   17 use strict;
  4         8  
  4         73  
5 4     4   1870 use LWP;
  4         144052  
  4         170  
6 4     4   46 use Time::HiRes;
  4         9  
  4         36  
7 4     4   408 use LWP::UserAgent;
  4         8  
  4         1402  
8              
9             our @ISA = ('LWP::UserAgent');
10              
11             =head1 NAME
12              
13             LWP::UserAgent::Throttled - Throttle requests to a site
14              
15             =head1 VERSION
16              
17             Version 0.09
18              
19             =cut
20              
21             our $VERSION = '0.09';
22              
23             =head1 SYNOPSIS
24              
25             Some sites with REST APIs, such as openstreetmap.org, will blacklist you if you do too many requests.
26             LWP::UserAgent::Throttled is a sub-class of LWP::UserAgent.
27              
28             use LWP::UserAgent::Throttled;
29             my $ua = LWP::UserAgent::Throttled->new();
30             $ua->throttle({ 'www.example.com' => 5 });
31             print $ua->get('http://www.example.com/page1.html');
32             sleep (2);
33             print $ua->get('http://www.example.com/page2.html'); # Will wait at least 3 seconds before the GET is sent
34              
35             =cut
36              
37             =head1 SUBROUTINES/METHODS
38              
39             =head2 send_request
40              
41             See L.
42              
43             =cut
44              
45             sub send_request {
46             # my ($request, $arg, $size) = @_;
47              
48 6     6 1 8205155 my $self = shift;
49 6         14 my $request = $_[0];
50 6         17 my $host = $request->uri()->host();
51              
52 6 100 100     340 if((defined($self->{'throttle'})) && $self->{'throttle'}{$host}) {
53 3 100       12 if($self->{'lastcallended'}{$host}) {
54 2         12 my $waittime = $self->{'throttle'}{$host} - (Time::HiRes::time() - $self->{'lastcallended'}{$host});
55              
56 2 50       8 if($waittime > 0) {
57 2         11896125 Time::HiRes::usleep($waittime * 1e6);
58             }
59             }
60             }
61 6         66 my $rc;
62 6 100       43 if(defined($self->{'_ua'})) {
63 1         4 $rc = $self->{'_ua'}->send_request(@_);
64             } else {
65 5         62 $rc = $self->SUPER::send_request(@_);
66             }
67 6         1314327 $self->{'lastcallended'}{$host} = Time::HiRes::time();
68 6         30 return $rc;
69             }
70              
71             =head2 throttle
72              
73             Get/set the number of seconds between each request for sites.
74              
75             my $ua = LWP::UserAgent::Throttled->new();
76             $ua->throttle({ 'search.cpan.org' => 0.1, 'www.example.com' => 1 });
77             print $ua->throttle('search.cpan.org'), "\n"; # prints 0.1
78             print $ua->throttle('perl.org'), "\n"; # prints 0
79              
80             When setting a throttle it returns itself,
81             so you can daisy chain messages.
82              
83             =cut
84              
85             sub throttle {
86 4     4 1 16225 my $self = shift;
87              
88 4 50       13 return if(!defined($_[0]));
89              
90 4 100       13 if(ref($_[0]) eq 'HASH') {
91 1         2 my %throttles = %{$_[0]};
  1         5  
92              
93 1         4 foreach my $host(keys %throttles) {
94 1         4 $self->{'throttle'}{$host} = $throttles{$host};
95             }
96 1         14 return $self;
97             }
98              
99 3         4 my $host = shift;
100 3 100       23 return $self->{'throttle'}{$host} ? $self->{'throttle'}{$host} : 0;
101             }
102              
103             =head2 ua
104              
105             Get/set the user agent if you wish to use that rather than itself
106              
107             use LWP::UserAgent::Cached;
108              
109             $ua->ua(LWP::UserAgent::Cached->new(cache_dir => '/home/home/.cache/lwp-cache'));
110             my $resp = $ua->get('https://www.nigelhorne.com'); # Throttles, then checks cache, then gets
111              
112             =cut
113              
114             sub ua {
115 1     1 1 4147 my($self, $ua) = @_;
116              
117 1 50       4 if($ua) {
118 1         4 $self->{_ua} = $ua;
119             }
120              
121 1         2 return $self->{_ua};
122             }
123              
124             =head1 AUTHOR
125              
126             Nigel Horne, C<< >>
127              
128             =head1 BUGS
129              
130             Please report any bugs or feature requests to C,
131             or through the web interface at
132             L.
133             I will be notified, and then you'll
134             automatically be notified of progress on your bug as I make changes.
135              
136             Redirects to other domains can confuse it, so you need to program those manually.
137              
138             =head1 SEE ALSO
139              
140             L
141              
142             =head1 SUPPORT
143              
144             You can find documentation for this module with the perldoc command.
145              
146             perldoc LWP::UserAgent::Throttled
147              
148             You can also look for information at:
149              
150             =over 4
151              
152             =item * MetaCPAN
153              
154             L
155              
156             =item * RT: CPAN's request tracker
157              
158             L
159              
160             =item * CPANTS
161              
162             L
163              
164             =item * CPAN Testers' Matrix
165              
166             L
167              
168             =item * CPAN Ratings
169              
170             L
171              
172             =item * CPAN Testers Dependencies
173              
174             L
175              
176             =back
177              
178             =head1 LICENSE AND COPYRIGHT
179              
180             Copyright 2017-2022 Nigel Horne.
181              
182             This program is released under the following licence: GPL2
183              
184             =cut
185              
186             1; # End of LWP::Throttle