File Coverage

blib/lib/WebService/CRUST.pm
Criterion Covered Total %
statement 19 21 90.4
branch n/a
condition n/a
subroutine 7 7 100.0
pod n/a
total 26 28 92.8


line stmt bran cond sub pod time code
1             package WebService::CRUST;
2              
3 1     1   37511 use strict;
  1         2  
  1         42  
4              
5 1     1   3910 use LWP;
  1         146520  
  1         37  
6 1     1   2121 use HTTP::Cookies;
  1         13874  
  1         27  
7 1     1   4961 use HTTP::Request::Common;
  1         2440  
  1         82  
8 1     1   7 use URI;
  1         3  
  1         28  
9 1     1   967 use URI::QueryParam;
  1         895  
  1         28  
10              
11 1     1   671 use WebService::CRUST::Result;
  0            
  0            
12              
13             our $VERSION = '0.7';
14              
15              
16              
17              
18             sub new {
19             my ( $class, %opt ) = @_;
20              
21             # Set a default formatter
22             $opt{format} or $opt{format} = [ 'XML::Simple', 'XMLin', 'XMLout' ];
23              
24             # Backwards compatibility
25             $opt{query} and $opt{params} = $opt{query};
26              
27             # Only use the library we're using to format with
28             eval sprintf "use %s", $opt{format}->[0];
29              
30             return bless { config => \%opt }, $class;
31             }
32              
33              
34             sub get {
35             my ( $self, $path, %h ) = @_;
36             return $self->request( 'GET', $path, %h );
37             }
38              
39             sub head {
40             my ( $self, $path, %h ) = @_;
41             return $self->request( 'HEAD', $path, %h );
42             }
43              
44             sub put {
45             my ( $self, $path, %h ) = @_;
46             return $self->request( 'PUT', $path, %h );
47             }
48              
49             sub post {
50             my ( $self, $path, %h ) = @_;
51             return $self->request( 'POST', $path, %h );
52             }
53              
54             sub request {
55             my ( $self, $method, $path, %h ) = @_;
56              
57             $method or die "Must provide a method";
58             $path or die "Must provide an action";
59              
60             # If we have a request key, then use that instead of tacking on a path
61             if ( $self->{config}->{request_key} ) {
62             $self->{config}->{base}
63             or die "request_key requires base option to be set";
64              
65             $h{ $self->{config}->{request_key} } = $path;
66             $path = undef;
67             }
68              
69             my $uri =
70             $self->{config}->{base}
71             ? URI->new_abs( $path, $self->{config}->{base} )
72             : URI->new($path);
73              
74             my $send =
75             $self->{config}->{params}
76             ? { %{ $self->{config}->{params} }, %h }
77             : \%h;
78              
79             my $req;
80             if ( $method eq 'POST' ) {
81             $self->debug( "POST: %s", $uri->as_string );
82              
83             $req = POST $uri->as_string, $send;
84             }
85             else {
86             $self->debug( "%s: %s", $method, $uri->as_string );
87              
88             my $content = delete $send->{-content};
89            
90             # If our content is a hash, then serialize it
91             if (ref $content) {
92             $content = $self->_format_request($content);
93             }
94            
95             $self->_add_param( $uri, $send );
96             $req = HTTP::Request->new( $method, $uri );
97             $content and $req->add_content($content);
98             }
99              
100             if ( $self->{config}->{basic_username}
101             and $self->{config}->{basic_password} )
102             {
103             $self->debug(
104             "Sending username/passwd for user %s",
105             $self->{config}->{basic_username}
106             );
107              
108             $req->authorization_basic(
109             $self->{config}->{basic_username},
110             $self->{config}->{basic_password}
111             );
112             }
113              
114             my $res = $self->ua->request($req);
115             $self->{response} = $res;
116              
117             $self->debug( "Request Sent: %s", $res->message );
118              
119             return WebService::CRUST::Result->new($self->_format_response($res), $self)
120             if $res->is_success;
121            
122             $self->debug( "Request was not successful" );
123              
124             return undef;
125             }
126              
127             sub response { return shift->{response} }
128              
129             sub _format_response {
130             my ( $self, $res, $format ) = @_;
131              
132             $format or $format = $self->{config}->{format};
133             my ( $class, $method ) = @$format;
134              
135             ref $method eq 'CODE' and return &$method( $res->content );
136              
137             my $o = $class->new( %{ $self->{config}->{opts} } );
138             return $o->$method( $res->content );
139             }
140             sub _format_request {
141             my ( $self, $req, $format ) = @_;
142            
143             $format or $format = $self->{config}->{format};
144            
145             my ($class, $deserialize, $method) = @$format;
146            
147             ref $method eq 'CODE' and return &$method( $req );
148            
149             my $o = $class->new( %{ $self->{config}->{opts} } );
150             return $o->$method( $req );
151             }
152              
153             sub ua {
154             my ( $self, $ua ) = @_;
155              
156             # If they provided a UA set it
157             $ua and $self->{ua} = $ua;
158              
159             # If we already have a UA then return it
160             $self->{ua} and return $self->{ua};
161              
162             $self->debug("Creating new UA");
163              
164             # Otherwise create our own UA
165             $ua = LWP::UserAgent->new;
166             $ua->agent( "WebService::CRUST/" . $VERSION ); # Set our User-Agent string
167             $ua->cookie_jar( {} ); # Support session cookies
168             $ua->env_proxy; # Support proxies
169             $ua->timeout( $self->{config}->{timeout} )
170             if $self->{config}->{timeout};
171              
172             $self->{ua} = $ua;
173             return $ua;
174             }
175              
176             sub _add_param {
177             my ( $self, $uri, $h ) = @_;
178              
179             while ( my ( $k, $v ) = each %$h ) { $uri->query_param_append( $k => $v ) }
180             }
181              
182             sub debug {
183             my ( $self, $msg, @args ) = @_;
184              
185             $self->{config}->{debug}
186             and printf STDERR "%s -- %s\n", __PACKAGE__, sprintf( $msg, @args );
187             }
188              
189             sub AUTOLOAD {
190             my $self = shift;
191             our $AUTOLOAD;
192              
193             # Don't override DESTROY
194             return if $AUTOLOAD =~ /::DESTROY$/;
195              
196             # Only get something if we have a base
197             $self->{config}->{base} or return;
198              
199             ( my $method = $AUTOLOAD ) =~ s/.*:://s;
200             $method =~ /(get|head|put|post)_(.*)/
201             and return $self->$1( $2, @_ );
202              
203             return $self->get( $method, @_ );
204             }
205              
206             1;
207              
208             __END__