2 # BioPerl module for Bio::DB::GenericWebAgent
4 # Please direct questions and support issues to <bioperl-l@bioperl.org>
6 # Cared for by Chris Fields <cjfields at bioperl dot org>
8 # Copyright Chris Fields
10 # You may distribute this module under the same terms as perl itself
12 # POD documentation - main docs before the code
14 # Interfaces with new GenericWebAgent interface
18 Bio::DB::GenericWebAgent - helper base class for parameter-based remote server
19 access and response retrieval.
25 See Bio::DB::EUtilities for an example implementation
29 WARNING: Please do B<NOT> spam the web servers with multiple requests.
31 Bio::DB::GenericWebAgent is a generic wrapper around a web agent
32 (LWP::UserAgent), an object which can retain, format, and build parameters for
33 the user agent (Bio::ParameterBaseI), and a BioPerl class parser that processes
34 response content received by the user agent. The Bio::ParameterBaseI object
35 should be state-aware, e.g. know when changes occur to parameters, so that
36 identical requests are not repeatedly sent to the server (this base class takes
37 this into consideration).
43 User feedback is an integral part of the
44 evolution of this and other Bioperl modules. Send
45 your comments and suggestions preferably to one
46 of the Bioperl mailing lists. Your participation
49 bioperl-l@lists.open-bio.org - General discussion
50 http://bioperl.org/Support.html - About the mailing lists
54 Please direct usage questions or support issues to the mailing list:
56 I<bioperl-l@bioperl.org>
58 rather than to the module maintainer directly. Many experienced and
59 reponsive experts will be able look at the problem and quickly
60 address it. Please include a thorough description of the problem
61 with code and data examples if at all possible.
65 Report bugs to the Bioperl bug tracking system to
66 help us keep track the bugs and their resolution.
67 Bug reports can be submitted via the web.
69 https://github.com/bioperl/bioperl-live/issues
73 Email cjfields at bioperl dot org
77 The rest of the documentation details each of the
78 object methods. Internal methods are usually
83 # Let the code begin...
85 package Bio
::DB
::GenericWebAgent
;
88 use base
qw(Bio::Root::Root);
91 my $LAST_INVOCATION_TIME = 0;
107 Usage : Bio::DB::GenericWebAgent->new(@args);
108 Function: Create new Bio::DB::GenericWebAgent instance.
110 Args : None specific to this base class. Inheriting classes will
111 likely set specific parameters in their constructor;
112 Bio::DB::GenericWebAgent is primarily a test bed.
117 my ($class, @args) = @_;
118 my $self = $class->SUPER::new
(@args);
119 $self->ua(LWP
::UserAgent
->new(env_proxy
=> 1,
120 agent
=> ref($self)));
121 $self->delay($self->delay_policy);
125 =head1 GenericWebAgent methods
127 =head2 parameter_base
129 Title : parameter_base
130 Usage : $dbi->parameter_base($pobj);
131 Function: Get/Set Bio::ParameterBaseI.
132 Returns : Bio::ParameterBaseI object
133 Args : Bio::ParameterBaseI object
137 # this will likely be overridden in subclasses
140 my ($self, $pobj) = @_;
142 $self->throw('Not a Bio::ParameterBaseI')
143 if !$pobj->isa('Bio::ParameterBaseI');
144 $self->{'_parameter_base'} = $pobj;
146 return $self->{'_parameter_base'};
153 Function: Get/Set LWP::UserAgent.
154 Returns : LWP::UserAgent
155 Args : LWP::UserAgent
160 my ($self, $ua) = @_;
161 if( defined $ua && $ua->isa("LWP::UserAgent") ) {
162 $self->{'_ua'} = $ua;
164 return $self->{'_ua'};
170 Usage : $agent->get_Response;
171 Function: Get the HTTP::Response object by passing it an HTTP::Request (generated from
172 Bio::ParameterBaseI implementation).
173 Returns : HTTP::Response object or data if callback is used
176 -cache_response - flag to cache HTTP::Response object;
177 Default is 1 (TRUE, caching ON)
179 These are passed on to LWP::UserAgent::request() if stipulated
181 -cb - use a LWP::UserAgent-compliant callback
182 -file - dumps the response to a file (handy for large responses)
183 Note: can't use file and callback at the same time
184 -read_size_hint - bytes of content to read in at a time to pass to callback
185 Note : Caching and parameter checking are set
189 # TODO deal with small state-related bug with file
192 my ($self, @args) = @_;
193 my ($cache, $file, $cb, $size) = $self->_rearrange([qw(CACHE_RESPONSE FILE CB READ_SIZE_HINT)],@args);
194 $self->throw("Can't have both callback and file") if $file && $cb;
195 # make -file accept more perl-like write-append type data.
196 $file =~ s{^>}{} if $file;
197 my @opts = grep {defined $_} ($file || $cb, $size);
198 $cache = (defined $cache && $cache == 0) ?
0 : 1;
199 my $pobj = $self->parameter_base;
200 if ($pobj->parameters_changed ||
202 !$self->{_response_cache
} ||
203 !$self->{_response_cache
}->content) {
205 $self->_sleep; # institute delay policy
206 $self->throw('No parameter object set; cannot form a suitable remote request') unless $pobj;
207 my $request = $pobj->to_request;
208 if ($self->authentication) {
209 $request->proxy_authorization_basic($self->authentication)
211 $self->debug("Request is: \n",$request->as_string);
212 # I'm relying on the useragent to throw the proper errors here
213 my $response = $ua->request($request, @opts);
214 if ($response->is_error) {
215 $self->throw("Response Error\n".$response->message);
217 return $self->{_response_cache
} = $response;
219 $self->debug("Returning cached HTTP::Response object\n");
221 $self->_dump_request_content($file);
222 # size isn't passed here, as the content is completely retrieved above
224 $cb && ref($cb) eq 'CODE' && $cb->($self->{_response_cache
}->content);
226 return $self->{_response_cache
};
233 Usage : $agent->get_Parser;
234 Function: Return HTTP::Response content (file, fh, object) attached to defined parser
237 Note : Abstract method; defined by implementation
242 shift->throw_not_implemented;
248 Usage : $secs = $self->delay($secs)
249 Function: get/set number of seconds to delay between fetches
250 Returns : number of seconds to delay
253 NOTE: the default is to use the value specified by delay_policy().
254 This can be overridden by calling this method.
260 return $self->{'_delay'} = shift if @_;
261 return $self->{'_delay'};
267 Usage : $secs = $self->delay_policy
268 Function: return number of seconds to delay between calls to remote db
269 Returns : number of seconds to delay
272 NOTE: The default delay policy is 3s. Override in subclasses to
273 implement delays. The timer has only second resolution, so the delay
274 will actually be +/- 1s.
286 Usage : $self->_sleep
287 Function: sleep for a number of seconds indicated by the delay policy
291 NOTE: This method keeps track of the last time it was called and only
292 imposes a sleep if it was called more recently than the delay_policy()
299 my $last_invocation = $LAST_INVOCATION_TIME;
300 if (time - $LAST_INVOCATION_TIME < $self->delay) {
301 my $delay = $self->delay - (time - $LAST_INVOCATION_TIME);
302 $self->debug("sleeping for $delay seconds\n");
304 # allows precise sleep timeout (builtin only allows integer seconds)
305 Time
::HiRes
::sleep($delay);
307 # allows precise sleep timeout (builtin only allows integer seconds)
309 # I hate this hack , but needed if we support 5.6.1 and
310 # don't want additional Time::HiRes prereq
311 select undef, undef, undef, $delay;
314 $LAST_INVOCATION_TIME = time;
317 =head1 LWP::UserAgent related methods
322 Usage : $httpproxy = $db->proxy('http') or
323 $db->proxy(['http','ftp'], 'http://myproxy' )
324 Function: Get/Set a proxy for use of proxy
325 Returns : a string indicating the proxy
326 Args : $protocol : an array ref of the protocol(s) to set/get
327 $proxyurl : url of the proxy to use for the specified protocol
328 $username : username (if proxy requires authentication)
329 $password : password (if proxy requires authentication)
334 my ($self,$protocol,$proxy,$username,$password) = @_;
335 return if ( !defined $protocol || !defined $proxy );
336 $self->authentication($username, $password)
337 if ($username && $password);
338 return $self->ua->proxy($protocol,$proxy);
341 =head2 authentication
343 Title : authentication
344 Usage : $db->authentication($user,$pass)
345 Function: Get/Set authentication credentials
346 Returns : Array of user/pass
347 Args : Array or user/pass
352 my ($self,$u,$p) = @_;
353 if( defined $u && defined $p ) {
354 $self->{'_authentication'} = [ $u,$p];
356 $self->{'_authentication'} && return @
{$self->{'_authentication'}};
359 # private method to dump any cached request data content into a passed filename
361 sub _dump_request_content
{
362 my ($self, $file) = @_;
363 return unless defined $self->{_response_cache
};
364 $self->throw("Must pass file name") unless $file;
365 require Bio
::Root
::IO
;
366 my $out = Bio
::Root
::IO
->new(-file
=> ">$file");
367 $out->_print($self->{_response_cache
}->content);