File Coverage

blib/lib/WWW/BigDoor.pm
Criterion Covered Total %
statement 98 99 98.9
branch 25 28 89.2
condition 14 20 70.0
subroutine 19 19 100.0
pod 4 4 100.0
total 160 170 94.1


line stmt bran cond sub pod time code
1             package WWW::BigDoor;
2              
3 18     18   100964 use warnings;
  18         44  
  18         721  
4 18     18   107 use strict;
  18         35  
  18         652  
5              
6 18     18   103 use Carp;
  18         47  
  18         1425  
7 18     18   2390 use Data::Dumper;
  18         37471  
  18         1249  
8 18     18   2212 use Digest::SHA qw(sha256_hex);
  18         8639  
  18         1208  
9 18     18   1241 use JSON;
  18         47241  
  18         133  
10 18     18   27870 use REST::Client;
  18         1306681  
  18         641  
11 18     18   20155 use UUID::Tiny;
  18         254999  
  18         2866  
12              
13             #use Smart::Comments -ENV;
14              
15 18     18   216 use base qw(Class::Accessor);
  18         43  
  18         21761  
16              
17 18     18   65019 use version; our $VERSION = qv( '0.1.1' );
  18         42587  
  18         126  
18              
19             BEGIN {
20 18     18   58 foreach my $method ( qw(GET POST PUT DELETE) ) {
21 18     18   2509 no strict 'refs'; ## no critic (ProhibitNoStrict)
  18         45  
  18         2219  
22              
23             #my $full_method_name = __PACKAGE__.'::'.$method;
24             ## full method name: $full_method_name
25 72         17097 *{__PACKAGE__ . '::' . $method} = sub {
26 185     185   503802 my $response_body = do_request( shift, $method, @_ );
27              
28 185 100 66     6134 my $decoded_response_body =
29             $response_body && $response_body ne q{}
30             ? decode_json( $response_body )
31             : undef; # TODO test for response_body eq q{}
32             ## decoded_response_body: $decoded_response_body
33              
34 185         1052 return $decoded_response_body;
35             }
36 72         236 }
37             }
38              
39             __PACKAGE__->follow_best_practice;
40             __PACKAGE__->mk_accessors(
41             qw(app_secret app_key api_host base_url request_result response_code response_content) );
42              
43             sub new {
44              
45 17     17 1 21697 my ( $class, $app_secret, $app_key, $api_host ) = @_;
46              
47 17         49 my $self = {};
48              
49 17         50 bless( $self, $class );
50              
51             ### check: defined $app_secret
52             ### check: defined $app_key
53              
54 17         78 $self->set_app_secret( $app_secret ); # TODO test for empty or undefined app_secret or app_key
55 17         405 $self->set_app_key( $app_key );
56 17   50     321 $self->set_api_host( $api_host || 'http://api.bigdoor.com' ); # TODO test for empty $api_host
57 17         268 $self->set_base_url( sprintf "/api/publisher/%s", $app_key );
58              
59 17         317 return $self;
60             }
61              
62             sub do_request {
63 185     185 1 686 my ( $self, $method, $endpoint, $params, $payload ) = @_;
64              
65 185         957 my $rc = REST::Client->new( {host => $self->get_api_host} );
66              
67 185         185754 my $url = $self->get_base_url . '/' . $endpoint;
68              
69             ## method: $method
70             ## url: $url
71              
72 185 100       3041 my $par = defined $params ? {%{$params}} : undef;
  92         492  
73 185 100       607 my $pay = defined $payload ? {%{$payload}} : undef;
  62         374  
74              
75 185         1555 ( $par, $pay ) = $self->_sign_request( $method, $url, $par, $pay );
76              
77             ### check: defined $par
78             # should be always defined by _sign_request
79 185         904 my $args = $rc->buildQuery( $par );
80              
81             ## args: $args
82             ## payload: Dumper($pay)
83              
84 185         153891 my $headers = {
85             'User-Agent' => sprintf( 'BigDoorKit-Perl/%s', $VERSION ),
86             'Content-Type' => 'application/x-www-form-urlencoded',
87             };
88              
89 185         600 my $post_body = q{};
90              
91 185 100       1152 if ( defined $pay ) {
92 64         955 require URI;
93 64         259 my $uri_encoded = URI->new( 'http:' );
94 64         68790 $uri_encoded->query_form( $pay );
95 64         11576 $post_body = $uri_encoded->query;
96              
97             ## post_body: $post_body
98             }
99              
100             ### URL: $url . $args
101 185         3584 my $result = $rc->request( $method, $url . $args, $post_body, $headers );
102              
103 185         265429 $self->set_request_result( $result );
104 185         3209 $self->set_response_code( $result->responseCode );
105 185         26718 $self->set_response_content( $result->responseContent );
106              
107             ### check: defined $result
108 185 50       12344 return unless defined $result;
109              
110             ### result: Dumper($result->{_res})
111             ### response code: $result->responseCode()
112             ### check: $result->responseCode < 300
113 185 100       1459 return if $result->responseCode >= 300;
114              
115             ## response content: $result->responseContent()
116             ## response headers: Dumper($result->responseHeaders())
117              
118 183         12305 my $response_body = $result->responseContent();
119             ### check: defined $response_body
120             ### response_body: $response_body
121              
122 183         16325 return $response_body;
123              
124             } ## end sub do_request
125              
126             sub _sign_request {
127 185     185   463 my ( $self, $method, $url, $params, $payload ) = @_;
128              
129             # FIXME use content copy
130 185         1111 my $is_postish = $method =~ /^(POST)|(PUT)$/ix;
131              
132 185 50 66     2048 if ( $is_postish && exists $payload->{'time'} ) {
133 0         0 $params->{'time'} = $payload->{'time'};
134             }
135 185 50       1131 unless ( exists $params->{'time'} ) {
136 185         921 $params->{'time'} = time;
137             }
138 185 100 66     1202 if ( $is_postish && !exists $payload->{'time'} ) {
139 64         165 $payload->{'time'} = $params->{'time'};
140             }
141 185 100 66     722 if ( $is_postish && !exists $payload->{'token'} ) {
142 64         283 $payload->{'token'} = $self->generate_token();
143             }
144 185 100 66     10799 if ( $method =~ /^DELETE$/ix && !exists $params->{'delete_token'} ) {
145 45         160 $params->{'delete_token'} = $self->generate_token();
146             }
147              
148 185         4956 $params->{'sig'} = $self->generate_signature( $url, $params, $payload );
149              
150             ### check: defined $params
151              
152 185         582 return ( $params, $payload );
153             } ## end sub _sign_request
154              
155             sub _flatten_params {
156 253     253   796 my ( $params ) = @_;
157              
158 253         382 my $result = q{};
159              
160 253         383 foreach my $k ( sort keys %{$params} ) {
  253         1358  
161 773 100 100     3443 next if $k eq 'sig' || $k eq 'format';
162 678         4214 $result .= sprintf '%s%s', $k, $params->{$k};
163             }
164 253         987 return $result;
165             }
166              
167             sub generate_token {
168 109     109 1 583 return unpack( "H*", create_UUID( UUID_V4 ) );
169             }
170              
171             sub generate_signature {
172 189     189 1 5043 my ( $self, $url, $params, $payload ) = @_;
173              
174 189         404 my $signature = $url;
175              
176 189 100       757 $signature .= _flatten_params( $params ) if defined $params;
177 189 100       667 $signature .= _flatten_params( $payload ) if defined $payload;
178              
179 189         944 $signature .= $self->get_app_secret();
180              
181             ### signature: $signature
182              
183 189         9832 return sha256_hex( $signature );
184             }
185              
186             1; # Magic true value required at end of module
187             __END__