File Coverage

blib/lib/Astro/Catalog/Transport/REST.pm
Criterion Covered Total %
statement 15 15 100.0
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 20 20 100.0


line stmt bran cond sub pod time code
1             package Astro::Catalog::Transport::REST;
2              
3             =head1 NAME
4              
5             Astro::Catalog::Transport::REST - A base class for REST query modules
6              
7             =head1 SYNOPSIS
8              
9             use base qw/ Astro::Catalog::Transport::REST /;
10              
11              
12             =head1 DESCRIPTION
13              
14             This class forms a base class for all the REST based query classes provided
15             in the C distribution (eg C).
16              
17             =cut
18              
19             # L O A D M O D U L E S --------------------------------------------------
20              
21 13     13   6823141 use 5.006;
  13         59  
  13         650  
22 13     13   81 use strict;
  13         24  
  13         507  
23 13     13   133 use warnings;
  13         26  
  13         572  
24 13     13   84 use warnings::register;
  13         26  
  13         6025  
25 13     13   85 use base qw/ Astro::Catalog::Query /;
  13         35  
  13         11915  
26             use vars qw/ $VERSION /;
27              
28             use LWP::UserAgent;
29             use Net::Domain qw(hostname hostdomain);
30             use File::Spec;
31             use Carp;
32              
33             # generic catalog objects
34             use Astro::Catalog;
35             use Astro::Catalog::Star;
36              
37             $VERSION = "4.31";
38              
39             =head1 REVISION
40              
41             $Id: REST.pm,v 1.7 2004/03/03 00:50:15 cavanagh Exp $
42              
43             =head1 METHODS
44              
45             =head2 Constructor
46              
47             =over 4
48              
49             =item B
50              
51             Create a new instance from a hash of options
52              
53             $q = new Astro::Catalog::Transport::REST( Coords => new Astro::Coords(),
54             Radius => $radius,
55             Bright => $magbright,
56             Faint => $magfaint,
57             Sort => $sort_type,
58             Number => $number_out );
59              
60             returns a reference to an query object. Must only called from
61             sub-classed constructors.
62              
63             RA and Dec are also allowed but are deprecated (since with only
64             RA/Dec the coordinates must always be supplied as J2000 space-separated
65             sexagesimal format).
66              
67             =cut
68              
69             sub new {
70             my $proto = shift;
71             my $class = ref($proto) || $proto;
72              
73             # bless the query hash into the class
74             my $block = bless { OPTIONS => {},
75             COORDS => undef,
76             URL => undef,
77             QUERY => undef,
78             USERAGENT => undef,
79             BUFFER => undef }, $class;
80              
81             # Configure the object [even if there are no args]
82             $block->configure( @_ );
83              
84             return $block;
85              
86             }
87              
88             =item B
89              
90             The LWP user agent mediating the web transaction.
91              
92             $ua = $q->useragent();
93              
94             Created automatically the first time it is requested.
95              
96             =cut
97              
98             sub useragent {
99             my $self = shift;
100             if (@_) {
101             my $ua = shift;
102             croak "Must be a LWP::UserAgent"
103             unless UNIVERSAL::isa($ua, "LWP::UserAgent");
104             $self->{USERAGENT} = $ua;
105             } else {
106             # If we have no UA but we have requested one, create it ourself
107             # This overcomes a chicken and egg situation if a subclass
108             # wants to go out on the net during object instantiation
109             # before configure() has been called
110              
111             # Setup the LWP::UserAgent
112             my $ua = new LWP::UserAgent( timeout => 30 );
113              
114             $self->useragent( $ua );
115             $ua->agent( $self->_default_useragent_id );
116              
117             # Grab Proxy details from local environment
118             $ua->env_proxy();
119              
120             }
121             return $self->{USERAGENT};
122             }
123              
124             =item B
125              
126             Returns an Astro::Catalog object resulting from the specific query.
127              
128             $catalog = $q->querydb();
129              
130             =cut
131              
132             sub querydb {
133             my $self = shift;
134              
135             # call the private method to make the actual query
136             $self->_make_query();
137              
138             # check for failed connect
139             return undef unless defined $self->{BUFFER};
140              
141             # return catalog
142             return $self->_parse_query();
143              
144             }
145              
146             =item B
147              
148             Return (or set) the current proxy for the catalog request.
149              
150             $usno->proxy( 'http://wwwcache.ex.ac.uk:8080/' );
151             $proxy_url = $usno->proxy();
152              
153             =cut
154              
155             sub proxy {
156             my $self = shift;
157              
158             # grab local reference to user agent
159             my $ua = $self->useragent;
160              
161             if (@_) {
162             my $proxy_url = shift;
163             $ua->proxy('http', $proxy_url );
164             }
165              
166             # return the current proxy
167             return $ua->proxy('http');
168              
169             }
170              
171             =item B
172              
173             Return (or set) the current timeout in seconds for the request.
174              
175             $usno->timeout( 30 );
176             $proxy_timeout = $usno->timeout();
177              
178             Default is 30 seconds.
179              
180             =cut
181              
182             sub timeout {
183             my $self = shift;
184              
185             # grab local reference to user agent
186             my $ua = $self->useragent;
187              
188             if (@_) {
189             my $time = shift;
190             $ua->timeout( $time );
191             }
192              
193             # return the current timeout
194             return $ua->timeout();
195              
196             }
197              
198             =item B
199              
200             The URL formed to build up a query. Made up of a root host name
201             (that can be set using the C method) and a fixed suffix that
202             specifies the path to the service (CGI or otherwise). This query URL
203             does not include the arguments to the CGI script (but will include
204             the question mark if appropriate).
205              
206             $query_url = $q->query();
207             $q->query_url( 'http://www.blah.org/cgi-bin/xxx.pl?');
208              
209             Care must be taken when setting this value.
210              
211             The argument is not validated. There may also need to be a new method
212             that returns the full URL including arguments.
213              
214             If no value has been supplied, a default will be returned.
215              
216             =cut
217              
218             sub query_url {
219             my $self = shift;
220             if (@_) {
221             $self->{QUERY} = shift;
222             }
223             if (defined $self->{QUERY}) {
224             return $self->{QUERY};
225             } else {
226             return "http://". $self->url .
227             "/" . $self->_default_url_path;
228             }
229              
230             return $self->{QUERY};
231             }
232              
233             =item B
234              
235             Return the current remote host for the query (the full URL
236             can be returned using the C method).
237              
238             $host = $q->url();
239              
240             Can also be used to set the root host for the URL (ie the
241             machine name but no path component)
242              
243             $q->url( "archive.eso.org" );
244              
245             if not defined the default URL is used (specified in the sub class).
246             This method should really be called C.
247              
248             Returns the default host name specified by the particular subclass
249             if a value has not been defined.
250              
251             =cut
252              
253             sub url {
254             my $self = shift;
255              
256             # SETTING URL
257             if (@_) {
258              
259             # set the url option
260             my $base_url = shift;
261             $self->{URL} = $base_url;
262             if( defined $base_url ) {
263             $self->query_url("http://$base_url/" .
264             $self->_default_url_path );
265             }
266             }
267              
268             # RETURNING remote host
269             if (defined $self->{URL}) {
270             return $self->{URL};
271             } else {
272             return $self->_default_remote_host();
273             }
274             }
275              
276             =item B
277              
278             Returns the user agent tag sent by the module to the server.
279              
280             $agent_tag = $q->agent();
281              
282             The user agent tag can not be set by this method.
283              
284             =cut
285              
286             sub agent {
287             my $self = shift;
288             return $self->useragent->agent();
289             }
290              
291             =back
292              
293             =begin __PRIVATE_METHODS__
294              
295             =head2 Private methods
296              
297             These methods are for internal use only.
298              
299             =over 4
300              
301             =item B<_default_remote_host>
302              
303             The default host name to use to build up the full URL.
304             Must be specified in a sub-class.
305              
306             $host = $q->_default_remote_host();
307              
308             =cut
309              
310             sub _default_remote_host {
311             croak "default remote host must be specified in subclass\n";
312             }
313              
314             =item B<_default_url_path>
315              
316             The path information after the host in the remote URL.
317             Must be overridden in a subclass.
318              
319             =cut
320              
321             sub _default_url_path {
322             croak "default url path information must be subclassed\n";
323             }
324              
325             =item B<_default_useragent_id>
326              
327             Default user agent ID used to declare the agent to the remote server.
328             Default format is
329              
330             __PACKAGE__/$VERSION ($HOST.$DOMAIN)
331              
332             This can be overridden in a subclass if necessary.
333              
334             =cut
335              
336             sub _default_useragent_id {
337             my $self = shift;
338             my $HOST = hostname();
339             my $DOMAIN = hostdomain();
340             my $package = ref($self);
341             my $pack_version;
342             {
343             # Need a symbolic reference
344             no strict 'refs';
345             $pack_version = ${ $package."::VERSION" };
346             }
347             $pack_version = 'UNKNOWN' unless defined $pack_version;
348             return "Astro::Catalog::REST/$pack_version ($HOST.$DOMAIN)";
349             }
350              
351              
352             =item B<_make_query>
353              
354             Private function used to make an query. Should not be called directly,
355             since it does not parse the results. Instead use the querydb()
356             method.
357              
358             =cut
359              
360             sub _make_query {
361             my $self = shift;
362              
363             # clean out the buffer
364             $self->{BUFFER} = "";
365              
366             # Build the query URL
367             my $URL = $self->_build_query();
368              
369             # Run the actual HTTP query
370             # and get the retrieved buffer
371             $self->{BUFFER} = $self->_fetch_url( $URL );
372              
373             return;
374             }
375              
376             =item B<_fetch_url>
377              
378             Simple wrapper around LWP to retrieve content from a remote
379             URL and return it as a single string.
380              
381             $result = $q->_fetch_url( $URL );
382              
383             =cut
384              
385             sub _fetch_url {
386             my $self = shift;
387             my $URL = shift;
388              
389             # grab the user agent
390             my $ua = $self->useragent;
391              
392             # build request
393             my $request = new HTTP::Request('GET', $URL);
394              
395             # grab page from web
396             my $reply = $ua->request($request);
397              
398             # Look at the result to see if it worked
399             if ( ${$reply}{"_rc"} eq 200 ) {
400             # stuff the page contents into the buffer
401             return ${$reply}{"_content"};
402             } else {
403             croak("Error ${$reply}{_rc}: Failed to establish network connection using url $URL");
404             }
405              
406             }
407              
408             =item B<_build_query>
409              
410             Build the URL to be sent to the remote service. The default method
411             concatenates the C along with all the defined query options
412             combined using key=value pairs separated by &.
413              
414             $url = $q->_build_query();
415              
416             If the URL can not be built simply by concatenation (eg it requires
417             token replacement), then a subclassed method will be required.
418              
419             =cut
420              
421             sub _build_query {
422             my $self = shift;
423              
424             # grab the base URL
425             my $URL = $self->query_url;
426             my $options = "";
427              
428             # loop round all the options keys and build the query
429             my %allow = $self->_get_allowed_options;
430              
431             # Translate options
432             my %translated = $self->_translate_options();
433              
434             foreach my $key ( keys %translated) {
435             $options .= "&$key=". $translated{$key}
436             if defined $translated{$key};
437             }
438              
439             # Remove the leading ampersand from the options list because
440             # it can cause some forms to fail.
441             $options =~ s/^&//;
442              
443             # build final query URL
444             $URL = $URL . $options;
445              
446             return $URL;
447             }
448              
449             =back
450              
451             =head1 COPYRIGHT
452              
453             Copyright (C) 2001 University of Exeter. All Rights Reserved.
454             Some modifications copyright (C) 2003 Particle Physics and Astronomy
455             Research Council. All Rights Reserved.
456              
457             This program was written as part of the eSTAR project and is free software;
458             you can redistribute it and/or modify it under the terms of the GNU Public
459             License.
460              
461             =head1 AUTHORS
462              
463             Alasdair Allan Eaa@astro.ex.ac.ukE,
464             Tim Jenness Etjenness@cpan.orgE
465              
466             =cut
467              
468             # L A S T O R D E R S ------------------------------------------------------
469              
470             1;