File Coverage

blib/lib/WWW/JSON.pm
Criterion Covered Total %
statement 77 82 93.9
branch 22 26 84.6
condition 9 16 56.2
subroutine 20 24 83.3
pod 6 7 85.7
total 134 155 86.4


line stmt bran cond sub pod time code
1             package WWW::JSON;
2 8     8   2084555 use 5.008005;
  8         28  
  8         299  
3 8     8   37 use strict;
  8         10  
  8         228  
4 8     8   46 use warnings;
  8         14  
  8         359  
5              
6             our $VERSION = "1.00";
7 8     8   875 use LWP::UserAgent;
  8         2390833  
  8         186  
8 8     8   4089 use Moo;
  8         90201  
  8         42  
9 8     8   13528 use Try::Tiny;
  8         8877  
  8         393  
10 8     8   44 use URI;
  8         13  
  8         136  
11 8     8   2940 use WWW::JSON::Response;
  8         23  
  8         310  
12 8     8   4652 use Safe::Isa;
  8         3103  
  8         1015  
13 8     8   43 use JSON::XS;
  8         12  
  8         364  
14 8     8   4143 use HTTP::Request::Common;
  8         14519  
  8         10720  
15              
16             has ua => (
17             is => 'lazy',
18             handles => [qw/timeout default_header/],
19             default => sub { LWP::UserAgent->new( %{ $_[0]->ua_options } ) }
20             );
21             has base_url => (
22             is => 'rw',
23             coerce => sub {
24             my $base_url = shift;
25             my $u;
26             if ( ref($base_url) eq 'ARRAY' ) {
27             my ( $url, $params ) = @{$base_url};
28             $u = URI->new($url);
29             $u->query_form(%$params);
30             }
31             else {
32             $u = URI->new($base_url);
33             }
34             if ( my $path = $u->path ) {
35             unless ( $path =~ m|/$| ) {
36             $path =~ s|$|/|;
37             $u->path($path);
38             }
39             }
40             return $u;
41             }
42             );
43             has body_params => ( is => 'rw', default => sub { +{} } );
44             has query_params => ( is => 'rw', default => sub { +{} } );
45             has post_body_format => (
46             is => 'rw',
47             default => sub { 'serialized' },
48             clearer => 1,
49             isa => sub {
50             die "Invalid post_body_format $_[0]"
51             unless ( $_[0] eq 'serialized' || $_[0] eq 'JSON' );
52             }
53             );
54             has json =>
55             ( is => 'ro', default => sub { JSON::XS->new->utf8->allow_nonref } );
56              
57             has content_type => ( is => 'rw', clearer => 1 );
58              
59             has default_response_transform => (
60             is => 'rw',
61             clearer => 1,
62             isa => sub {
63             die "default_response_transform takes a coderef"
64             unless ref( $_[0] ) eq 'CODE';
65             }
66             );
67              
68             has ua_options => ( is => 'lazy', default => sub { +{} } );
69              
70             with 'WWW::JSON::Role::Authentication';
71             my %METHOD_DISPATCH = (
72             GET => \&HTTP::Request::Common::GET,
73             POST => \&HTTP::Request::Common::POST,
74             PUT => \&HTTP::Request::Common::PUT,
75             DELETE => \&HTTP::Request::Common::DELETE,
76             HEAD => \&HTTP::Request::Common::HEAD
77             );
78              
79 7     7 1 2495 sub get { shift->req( 'GET', @_ ) }
80 10     10 1 3463 sub post { shift->req( 'POST', @_ ) }
81 0     0 1 0 sub put { shift->req( 'PUT', @_ ) }
82 0     0 1 0 sub delete { shift->req( 'DELETE', @_ ) }
83 0     0 0 0 sub head { shift->req( 'HEAD', @_ ) }
84              
85              
86             sub _http_method_uses_post_body {
87 44     44   246 my ($self,$method) = @_;
88 44   66     298 return ($method eq 'POST' || $method eq 'PUT');
89             }
90              
91             sub req {
92 17     17 1 39 my ( $self, $method, $path, $params, $opts ) = @_;
93 17 100       85 $params = {} unless defined($params);
94 17 100       55 $opts = {} unless defined($opts);
95 17         18 my $body_params;
96 17 100       43 $body_params = { %{ $self->body_params }, %{$params} }
  10         65  
  10         29  
97             if $self->_http_method_uses_post_body($method);
98 17 100       74 ( $path, $params ) = $self->_do_templating( $path, $params )
99             if ( $path =~ /\[\%.*\%\]/ );
100 17 50 33     98 unless ( $path->$_isa('URI') && $path->scheme ) {
101 17         233 $path =~ s|^/|./|;
102 17         81 $path = URI->new($path);
103             }
104              
105 17 100       701 my $abs_uri =
106             ( $path->scheme ) ? $path : URI->new_abs( $path, $self->base_url );
107              
108 17         8528 $abs_uri->query_form(
109             $self->_determine_query_params( $method, $path, $params,
110             $opts->{query_params} )
111             );
112              
113 17         420 my $request_obj = $self->_create_request_obj( $method, $abs_uri, $body_params );
114              
115 17         4082 return $self->http_request( $request_obj);
116             }
117              
118             sub _determine_query_params {
119 17     17   43 my ( $self, $method, $path, $params, $opt_params ) = @_;
120 17         454 my %query_params = (
121             $self->base_url->query_form,
122 17 50 66     330 ($self->query_params) ? %{$self->query_params} : (),
    100          
    100          
123             $path->query_form,
124             ( $params && ! $self->_http_method_uses_post_body($method) ) ? %$params : (),
125             ($opt_params) ? (%$opt_params) : ()
126             );
127 17         58 return %query_params;
128             }
129              
130             sub _do_templating {
131 3     3   4 my ( $self, $path, $params ) = @_;
132 3         11 my %modified_params = %$params;
133 3         7 for my $key ( grep { $_ =~ /^-/ } keys(%$params) ) {
  6         14  
134 4         12 (my $search_key = $key) =~ s/^-//;
135 4 50       68 delete $modified_params{$key}
136             if ( $path =~ s/\[\%\s*$search_key\s*\%\]/$params->{$key}/g );
137             }
138 3         9 return ( $path, \%modified_params );
139             }
140              
141             sub body_param {
142 0     0 1 0 my ( $self, $k, $v ) = @_;
143 0         0 $self->body_param->{$k} = $v;
144             }
145              
146             sub _create_post_body {
147 10     10   22 my ( $self, $p ) = @_;
148 10 100       108 if ( $self->post_body_format eq 'JSON' ) {
149             return (
150 1   50     19 'Content-Type' => $self->content_type || 'application/json',
151             Content => $self->json->encode($p)
152             );
153             }
154             return (
155 9   50     2244 Content => $self->_encode_content_body($p),
156             'Content-Type' => $self->content_type || 'application/x-www-form-urlencoded'
157             );
158             }
159              
160             sub _encode_content_body {
161 9     9   15 my ($self,$p) = @_;
162 9         40 my $u = URI->new;
163 9         258 $u->query_form(%$p);
164 9         485 return $u->query;
165             }
166              
167             sub _create_request_obj {
168 17     17   42 my ( $self, $method, $uri, $p ) = @_;
169 17 50       64 my $dispatch = $METHOD_DISPATCH{$method}
170             or die "Method $method not implemented";
171              
172 17         23 my %payload;
173              
174 17 100 66     59 if ( $p && $self->_http_method_uses_post_body($method)) {
175 10         31 %payload = $self->_create_post_body($p);
176             }
177 17         261 return $dispatch->( $uri->as_string, %payload );
178             }
179              
180             sub http_request {
181             my ( $self, $request_obj ) = @_;
182             my $resp = $self->ua->request($request_obj);
183              
184             return WWW::JSON::Response->new(
185             {
186             http_response => $resp,
187             _response_transform => $self->default_response_transform,
188             json => $self->json,
189             request_object => $request_obj,
190             }
191             );
192             }
193              
194             1;
195             __END__