File Coverage

blib/lib/WWW/Vonage/API.pm
Criterion Covered Total %
statement 116 124 93.5
branch 30 42 71.4
condition 15 21 71.4
subroutine 23 23 100.0
pod 8 8 100.0
total 192 218 88.0


line stmt bran cond sub pod time code
1             package WWW::Vonage::API;
2              
3 5     5   565987 use 5.010001;
  5         20  
4 5     5   33 use strict;
  5         22  
  5         128  
5 5     5   18 use warnings;
  5         10  
  5         448  
6              
7             our $VERSION = '0.001';
8             our $Debug = 0;
9             our $Test = 0;
10 5     5   3663 use LWP::UserAgent ();
  5         315165  
  5         210  
11 5     5   49 use URI::Escape qw(uri_escape uri_escape_utf8);
  5         10  
  5         398  
12 5     5   3645 use JSON;
  5         57572  
  5         27  
13 5     5   861 use Carp 'croak';
  5         9  
  5         268  
14 5     5   29 use List::Util '1.29', 'pairs';
  5         16  
  5         624  
15 5     5   2929 use Data::Dumper;
  5         45746  
  5         7754  
16 11     11 1 33 sub API_Domain { 'nexmo.com' }
17 8     8 1 26 sub API_Version { 'v1' }
18 9     9 1 27 sub API_Region { 'api' }
19              
20             my %account_sid = ();
21             my %auth_token = ();
22             my %api_version = ();
23             my %api_region = ();
24             my %api_domain = ();
25             my %lwp_callback = (); #not used yet
26             my %utf8 = (); #not documented
27              
28             sub new {
29 18     18 1 926928 my $class = shift;
30 18         79 my %args = @_;
31              
32 18         52 my $self = bless \( my $ref ), $class;
33              
34 18         51 for my $argument (qw ( API_Key API_Secret )) {
35 32 100       1050 exists $args{$argument}
36             or croak $class . "->new requires $argument argument";
37             }
38              
39 12   50     97 $account_sid{$self} = $args{API_Key} || '';
40 12   50     46 $auth_token{$self} = $args{API_Secret} || '';
41             $api_version{$self} =
42 12 100       66 defined $args{API_Version} ? lc( $args{API_Version} ) : API_Version();
43             $api_region{$self} =
44 12 100       63 defined $args{API_Region} ? lc( $args{API_Region} ) : API_Region();
45             $api_domain{$self} =
46 12 100       50 defined $args{API_Domain} ? lc( $args{API_Domain} ) : API_Domain();
47 12 100       36 $Test = defined $args{_test} ? 1 : $Test;
48              
49 12   50     96 $lwp_callback{$self} = $args{LWP_Callback} || undef;
50 12   50     60 $utf8{$self} = $args{utf8} || undef;
51              
52 12         76 return $self;
53             }
54              
55             sub GET {
56 11     11 1 6307 _do_request( shift, METHOD => 'GET', Path => shift, PAYLOAD => shift, @_ );
57             }
58              
59             sub POST {
60 7     7 1 4555 _do_request( shift, METHOD => 'POST', Path => shift, PAYLOAD => shift, @_ );
61             }
62              
63             sub PUT {
64 1     1 1 632 _do_request( shift, METHOD => 'PUT', Path => shift, PAYLOAD => shift, @_ );
65             }
66              
67             sub PATCH {
68 1     1 1 654 _do_request(
69             shift,
70             METHOD => 'PATCH',
71             Path => shift,
72             PAYLOAD => shift,
73             @_
74             );
75             }
76              
77             sub DELETE {
78 2     2   1446 _do_request(
79             shift,
80             METHOD => 'DELETE',
81             Path => shift,
82             PAYLOAD => shift,
83             @_
84             );
85             }
86              
87             ## METHOD => GET|POST|PUT|DELETE|PATCH
88             ## API => Messages
89             ## Recordings|Notifications|etc.
90             sub _do_request {
91 22     22   28 my $self = shift;
92              
93 22         71 my %args = @_;
94              
95 22         88 my $lwp = LWP::UserAgent->new;
96             $lwp_callback{$self}->($lwp)
97 22 50       9298 if ref( $lwp_callback{$self} ) eq 'CODE';
98              
99 22         63 $lwp->agent("perl-WWW-Vonage-API/$VERSION");
100              
101 22         953 my $method = delete $args{METHOD};
102 22         30 my $payload = delete $args{PAYLOAD};
103 22         42 my $path = lc( delete( $args{Path} ) );
104              
105 22 50       37 print STDERR "Raw payload: " . Dumper($payload) . "\n"
106             if $Debug;
107              
108 22         49 my $domain = $self->_build_domain(%args);
109              
110 22 50       37 print STDERR "Raw domain " . $domain . "\n"
111             if $Debug;
112              
113 22         45 my $url = $self->_build_url( $method, $domain, $path, $payload, %args );
114              
115 22 50       40 print STDERR "Request URL " . $url . "\n"
116             if $Debug;
117              
118 22         79 my $request = HTTP::Request->new( $method => $url );
119 22         15086 my $content = undef;
120 22 100 100     115 if ( ( $method eq 'POST' or $method eq 'PATCH' or $method eq 'PUT' )
      100        
121             and ref($payload) eq "HASH" )
122             {
123              
124 7         70 my $json = JSON->new->canonical(1);
125              
126 7         43 $content = $json->encode($payload);
127 7         20 $request->content($content);
128             }
129              
130 22 50       179 if ($Test) { #used only for testing
131             return {
132 22         336 url => $url,
133             payload => $content
134             };
135             }
136 0         0 $request->header( 'Content-Type' => 'application/json' );
137 0         0 $request->header( 'Accept' => 'application/json' );
138              
139 0         0 $request->authorization_basic( $account_sid{$self}, $auth_token{$self} );
140              
141 0         0 local $ENV{HTTPS_DEBUG} = $Debug;
142              
143 0         0 my $response = $lwp->request($request);
144              
145 0 0       0 print STDERR "Request sent: " . $request->as_string . "\n"
146             if $Debug;
147              
148 0 0       0 print STDERR "Raw Response received: " . Dumper($response) . "\n"
149             if $Debug;
150              
151             return {
152 0         0 code => $response->code,
153             message => $response->message,
154             content => $response->content
155             };
156             }
157              
158             sub _build_url { #did it this way so they can be tested
159 22     22   20 my $self = shift;
160 22         27 my ($method) = shift;
161 22         29 my ($domain) = shift;
162 22         27 my ($path) = shift;
163 22         25 my ($payload) = shift;
164 22         48 my %args = @_;
165              
166 22         48 my $url = sprintf( 'https://%s/%s', $domain, $path );
167              
168 22 100 100     60 if ( $method eq 'GET' and ref($payload) eq "HASH" ) {
169 5         10 my $query_string = $self->_build_query_string($payload);
170              
171 5 50       12 print STDERR "Encoded query_string: " . $query_string . "\n"
172             if $Debug;
173              
174 5         7 $url .= '?' . $query_string;
175             }
176              
177 22         39 return $url;
178              
179             }
180              
181             ## builds a string suitable for LWP's content() method
182             sub _build_query_string {
183 5     5   5 my $self = shift;
184 5         7 my ($payload) = @_;
185              
186 5 50       14 my $escape_method = $utf8{$self} ? \&uri_escape_utf8 : \&uri_escape;
187 5         7 my @arguments;
188 5         6 foreach my $key ( sort( keys( %{$payload} ) ) ) {
  5         16  
189             push( @arguments,
190             &$escape_method($key) . '='
191 9   50     94 . &$escape_method( $payload->{$key} // '' ) );
192             }
193              
194 5   50     126 return join( '&', @arguments ) || '';
195             }
196              
197             sub _build_domain {
198 28     28   2584 my $self = shift;
199              
200 28         49 my %args = @_;
201 28         61 my $api_ver = $api_version{$self};
202 28         47 my $region = $api_region{$self};
203 28         44 my $domain = $api_domain{$self};
204              
205 28 100       58 if ( $args{API_Version} ) {
206 16         20 $api_ver = lc( $args{API_Version} );
207 16         27 $api_version{$self} = $api_ver;
208             }
209              
210 28         45 $api_ver = "/" . $api_ver;
211              
212 28 100       51 $api_ver = ''
213             if ($api_ver) eq '/none';
214              
215 28 100       48 if ( $args{API_Region} ) {
216 8         12 $region = lc( $args{API_Region} );
217 8         28 $api_region{$self} = $region;
218             }
219              
220 28 100       49 if ( $args{API_Domain} ) {
221 1         2 $domain = lc( $args{API_Domain} );
222 1         2 $api_domain{$self} = $domain;
223             }
224              
225 28         83 return $region . "." . $domain . $api_ver
226              
227             }
228              
229             sub DESTROY {
230 18     18   4024 my $self = $_[0];
231              
232 18         57 delete( $account_sid{$self} );
233 18         43 delete( $auth_token{$self} );
234 18         36 delete( $api_version{$self} );
235 18         54 delete( $api_region{$self} );
236 18         36 delete( $api_domain{$self} );
237 18         32 delete( $lwp_callback{$self} );
238 18         41 delete( $utf8{$self} );
239              
240 18         114 my $super = $self->can("SUPER::DESTROY");
241 18 50       551 goto &$super if $super;
242             }
243              
244             1;
245              
246             __END__