File Coverage

lib/eBay/API/Simple/JSON.pm
Criterion Covered Total %
statement 9 9 100.0
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 12 12 100.0


line stmt bran cond sub pod time code
1             package eBay::API::Simple::JSON;
2              
3 1     1   1151 use strict;
  1         3  
  1         30  
4 1     1   4 use warnings;
  1         2  
  1         26  
5              
6 1     1   5 use base 'eBay::API::SimpleBase';
  1         3  
  1         73  
7             use JSON;
8             use HTTP::Request;
9             use HTTP::Headers;
10             use XML::Simple;
11             use URI::Escape;
12             use utf8;
13              
14             our $DEBUG = 0;
15              
16             =head1 NAME
17              
18             eBay::API::Simple::JSON - Support for grabbing an RSS feed via API call
19              
20             =head1 USAGE
21              
22             my $api = eBay::API::Simple::JSON->new();
23              
24             my $data = {
25             "user_eais_token" => "tim",
26             "body_text" => "mytext",
27             "foo" => "bar",
28             "greener_alt_topic" => "/green/api/v1/greenerAlternativeTopic/2/",
29             "items"=> [ {
30             "ebay_item_id"=> "250814913221",
31             "photo"=> "http=>//thumbs2.ebaystatic.com/m/m9X7sXOK303v4e_fgxm_-7w/140.jpg",
32             "price"=> 2.96,
33             "title"=> "TEST PUT - VAPUR 16 OZ FLEXIBLE FOLDABLE WATER BOTTLE BPA FREE"
34             } ],
35             "meta_title"=> "Foldable bottles can be stashed away when the water is gone",
36             "title"=> "TEST PUT - Foldable bottles can be stashed away when the water is gone"
37             };
38              
39             $api->execute(
40             'http://localhost-django-vm.ebay.com/green/api/v1/greenerAlternative/',
41             $data
42             );
43              
44             print $api->request_content() ."\n";
45              
46             if ( $api->has_error() ) {
47             print "FAILED: " . $api->response_content();
48             #print "FAILED: " . $api->response_hash->{error_message} . "\n";
49             }
50             else {
51             print "SUCCESS!\n";
52             print $api->response_object->header('Location') . "\n";
53             }
54            
55             my $hash = $call->response_hash();
56              
57             # execution methods for "GET", "POST", "PUT", and "DELETE" requests
58             $api->get( $endpoint );
59             $api->post( $endpoint, data );
60             $api->put( $endpoint, $data );
61             $api->delete( $endpoint );
62            
63             =head1 PUBLIC METHODS
64              
65             =head2 new( { %options } }
66              
67             my $call = ebay::API::Simple::JSON->new();
68              
69             =cut
70              
71             sub new {
72             my $class = shift;
73             my $self = $class->SUPER::new(@_);
74              
75             $self->api_config->{request_method} ||= 'POST';
76              
77             return $self;
78             }
79              
80             =head2 prepare( $url, $%args )
81              
82             $call->prepare(
83             'http://sfbay.craigslist.org/search/sss',
84             { query => 'shirt', format => 'rss', }
85             );
86            
87             This method will construct the API request using the supplied URL.
88              
89             =head3 Options
90              
91             =over 4
92              
93             =item $url (required)
94              
95             Feed URL to fetch
96              
97             =item %$args (optional)
98              
99             The supplied args will be encoded and appended to the URL
100              
101             =back
102              
103             =cut
104              
105             sub prepare {
106             my $self = shift;
107              
108             $self->{url} = shift;
109              
110             if ( ! defined $self->{url} ) {
111             die "missing url";
112             }
113              
114             # collect the optional args
115             $self->{request_data} = shift;
116             }
117              
118             =head2 process()
119              
120             This method will process the API response.
121              
122             =cut
123              
124             sub process {
125             my $self = shift;
126              
127             $self->SUPER::process();
128              
129             $self->response_hash(); # build the hash now to detect errors
130             }
131              
132             =head2 get( $url )
133              
134             execute a "GET" request to the specified endpoint
135              
136             =cut
137              
138             sub get {
139             my $self = shift;
140             $self->{custom_method} = 'GET';
141             $self->execute(@_);
142             $self->{custom_method} = undef;
143             }
144              
145             =head2 post( $url )
146              
147             execute a "POST" request to the specified endpoint
148              
149             =cut
150              
151             sub post {
152             my $self = shift;
153             $self->{custom_method} = 'POST';
154             $self->execute(@_);
155             $self->{custom_method} = undef;
156             }
157              
158             =head2 put( $url )
159              
160             execute a "PUT" request to the specified endpoint
161              
162             =cut
163              
164             sub put {
165             my $self = shift;
166             $self->{custom_method} = 'PUT';
167             $self->execute(@_);
168             $self->{custom_method} = undef;
169             }
170              
171             =head2 delete( $url )
172              
173             execute a "DELETE" request to the specified endpoint
174              
175             =cut
176              
177             sub delete {
178             my $self = shift;
179             $self->{custom_method} = 'DELETE';
180             $self->execute(@_);
181             $self->{custom_method} = undef;
182             }
183              
184             =head1 BASECLASS METHODS
185              
186             =head2 request_agent
187              
188             Accessor for the LWP::UserAgent request agent
189              
190             =head2 request_object
191              
192             Accessor for the HTTP::Request request object
193              
194             =head2 request
195              
196             Accessor for the HTTP::Request request object
197              
198             =cut
199              
200             sub request {
201             my $self = shift;
202             return $self->request_object();
203             }
204              
205             =head2 request_content
206              
207             Accessor for the complete request body from the HTTP::Request object
208              
209             =head2 response_content
210              
211             Accessor for the HTTP response body content
212              
213             =head2 response_object
214              
215             Accessor for the HTTP::Response response object
216              
217             =head2 response
218              
219             Accessor for the HTTP::Response response object
220              
221             =cut
222              
223             sub response {
224             my $self = shift;
225             return $self->response_object;
226             }
227              
228             =head2 response_dom
229              
230             Accessor for the LibXML response DOM
231              
232             =cut
233              
234             sub response_dom {
235             die "can't use with the JSON backend";
236             }
237              
238             =head2 response_hash
239              
240             Accessor for the hashified response content
241              
242             =cut
243              
244             sub response_hash {
245             my $self = shift;
246              
247             if ( ! defined $self->{response_hash} && $self->response_content ) {
248             eval {
249             $self->{response_hash} = decode_json( $self->response_content );
250             };
251             if ( $@ ) {
252             $self->errors_append( { 'decode_error' => $@ } );
253             }
254             }
255              
256             return $self->{response_hash};
257             }
258              
259             =head2 response_json
260              
261             Accessor for the json response content
262              
263             =cut
264              
265             sub response_json {
266             my $self = shift;
267             return $self->response_content;
268             }
269              
270             =head2 nodeContent( $tag, [ $dom ] )
271              
272             Helper for LibXML that retrieves node content
273              
274             =cut
275              
276             sub nodeContent {
277             die "not implemented for the JSON backend";
278             }
279              
280             =head2 errors
281              
282             Accessor to the hashref of errors
283              
284             =head2 has_error
285              
286             Returns true if the call contains errors
287              
288             =cut
289              
290             sub has_error {
291             my $self = shift;
292            
293             my $has_error = (keys( %{ $self->errors } ) > 0) ? 1 : 0;
294             return 1 if $has_error;
295             return $self->response_object->is_error;
296             }
297              
298             =head2 errors_as_string
299              
300             Returns a string of API errors if there are any.
301              
302             =cut
303              
304             sub errors_as_string {
305             my $self = shift;
306            
307             return "" unless $self->has_error;
308              
309             my @e;
310             for my $k ( keys %{ $self->errors } ) {
311             push( @e, $k . '-' . $self->errors->{$k} );
312             }
313              
314             if ( $self->response_object->is_error ) {
315             push( @e, $self->response_content );
316             }
317            
318             return join( "\n", @e );
319            
320             }
321              
322             =head1 PRIVATE METHODS
323              
324             =head2 _get_request_body
325              
326             This method supplies the JSON body for the web service request
327              
328             =cut
329              
330             sub _get_request_body {
331             my $self = shift;
332             return undef if ! defined $self->{request_data};
333             my $body;
334             eval {
335             my $json = JSON->new->utf8;
336             $body = $json->allow_blessed->convert_blessed->encode( $self->{request_data} );
337             };
338             if ( $@ ) {
339             $self->errors_append( { 'decode_error' => $@ } );
340             }
341             return $body;
342             }
343              
344             =head2 _get_request_headers
345              
346             This methods supplies the headers for the RSS API call
347              
348             =cut
349              
350             sub _get_request_headers {
351             my $self = shift;
352            
353             my $obj = HTTP::Headers->new();
354             $obj->push_header( 'Content-Type' => 'application/json' );
355             return $obj;
356             }
357              
358             =head2 _get_request_object
359              
360             This method creates the request object and returns to the parent class
361              
362             =cut
363              
364             sub _get_request_object {
365             my $self = shift;
366            
367             my $body = $self->_get_request_body;
368            
369             my $request_method = $self->{custom_method};
370             if ( ! $request_method ) {
371             $request_method = defined $body ? 'POST' : 'GET';
372             }
373            
374             my $request_obj = HTTP::Request->new(
375             $request_method,
376             $self->{url},
377             $self->_get_request_headers,
378             $self->_get_request_body,
379             );
380              
381             if( $self->api_config->{authorization_basic}{enabled} ) {
382             $request_obj->authorization_basic(
383             $self->api_config->{authorization_basic}{username},
384             $self->api_config->{authorization_basic}{password}
385             );
386             }
387              
388             return $request_obj;
389             }
390              
391             1;
392              
393             =head1 AUTHOR
394              
395             Tim Keefer
396              
397             =head1 COPYRIGHT
398              
399             Tim Keefer 2009
400              
401             =cut