File Coverage

blib/lib/AsposeTasksCloud/ApiClient.pm
Criterion Covered Total %
statement 57 170 33.5
branch 0 68 0.0
condition 0 33 0.0
subroutine 19 33 57.5
pod 0 14 0.0
total 76 318 23.9


line stmt bran cond sub pod time code
1             package AsposeTasksCloud::ApiClient;
2              
3 1     1   5 use strict;
  1         2  
  1         26  
4 1     1   4 use warnings;
  1         2  
  1         20  
5 1     1   4 use utf8;
  1         1  
  1         4  
6              
7 1     1   17 use MIME::Base64;
  1         1  
  1         37  
8 1     1   5 use LWP::UserAgent;
  1         5  
  1         20  
9 1     1   5 use HTTP::Headers;
  1         1  
  1         16  
10 1     1   4 use HTTP::Response;
  1         4  
  1         19  
11 1     1   4 use HTTP::Request::Common qw(DELETE POST GET HEAD PUT);
  1         1  
  1         47  
12 1     1   4 use HTTP::Status;
  1         2  
  1         181  
13 1     1   5 use URI::Query;
  1         2  
  1         28  
14 1     1   4 use JSON;
  1         2  
  1         6  
15 1     1   96 use URI::Escape;
  1         2  
  1         36  
16 1     1   5 use Scalar::Util;
  1         1  
  1         31  
17 1     1   4 use Log::Any qw($log);
  1         2  
  1         5  
18 1     1   160 use Carp;
  1         2  
  1         48  
19 1     1   5 use Module::Runtime qw(use_module);
  1         1  
  1         5  
20 1     1   49 use Digest::HMAC_SHA1;
  1         2  
  1         24  
21 1     1   4 use MIME::Base64;
  1         1  
  1         32  
22              
23 1     1   228 use AsposeTasksCloud::Configuration;
  1         2  
  1         1306  
24              
25             sub new
26             {
27            
28 0 0 0 0 0   if(not defined $AsposeTasksCloud::Configuration::app_sid or $AsposeTasksCloud::Configuration::app_sid eq ''){
29 0           croak("Aspose Cloud App SID key is missing.");
30             }
31            
32 0 0 0       if(not defined $AsposeTasksCloud::Configuration::api_key or $AsposeTasksCloud::Configuration::api_key eq ''){
33 0           croak("Aspose Cloud API key is missing.");
34             }
35            
36 0           my $class = shift;
37 0           my (%args) = (
38             'ua' => LWP::UserAgent->new,
39             'base_url' => $AsposeTasksCloud::Configuration::api_server,
40             @_
41             );
42            
43 0           return bless \%args, $class;
44             }
45              
46             # Set the user agent of the API client
47             #
48             # @param string $user_agent The user agent of the API client
49             #
50             sub set_user_agent {
51 0     0 0   my ($self, $user_agent) = @_;
52 0           $self->{http_user_agent}= $user_agent;
53             }
54              
55             # Set timeout
56             #
57             # @param integer $seconds Number of seconds before timing out [set to 0 for no timeout]
58             #
59             sub set_timeout {
60 0     0 0   my ($self, $seconds) = @_;
61 0 0         if (!looks_like_number($seconds)) {
62 0           croak('Timeout variable must be numeric.');
63             }
64 0           $self->{http_timeout} = $seconds;
65             }
66              
67             # make the HTTP request
68             # @param string $resourcePath path to method endpoint
69             # @param string $method method to call
70             # @param array $queryParams parameters to be place in query URL
71             # @param array $postData parameters to be placed in POST body
72             # @param array $headerParams parameters to be place in request header
73             # @return mixed
74             sub call_api {
75 0     0 0   my $self = shift;
76 0           my ($resource_path, $method, $query_params, $post_params, $header_params, $body_data, $auth_settings) = @_;
77            
78 0           $resource_path =~ s/\Q{appSid}\E/$AsposeTasksCloud::Configuration::app_sid/g;
79            
80 0           my $_url = $self->{base_url} . $resource_path;
81            
82             # update signature
83 0           my $signature = $self->sign($_url, $AsposeTasksCloud::Configuration::app_sid, $AsposeTasksCloud::Configuration::api_key);
84            
85 0           $_url = $_url . '&signature=' . $signature;
86            
87 0 0         if($AsposeTasksCloud::Configuration::debug){
88 0           print "\nFinal URL: ".$method."::".$_url."\n";
89             }
90             # body data
91 0 0 0       $body_data = to_json($body_data->to_hash) if defined $body_data && $body_data->can('to_hash'); # model to json string
92 0 0         my $_body_data = keys %$post_params > 1 ? $post_params : $body_data;
93            
94             #my $_body_data = $body_data;
95            
96             # Make the HTTP request
97 0           my $_request;
98 0 0         if ($method eq 'POST') {
    0          
    0          
    0          
    0          
    0          
99             # multipart
100             $header_params->{'Content-Type'} = lc $header_params->{'Content-Type'} eq 'multipart/form' ?
101 0 0         'form-data' : $header_params->{'Content-Type'};
102            
103 0           $_request = POST($_url, %$header_params, Content => $_body_data);
104            
105             }
106             elsif ($method eq 'PUT') {
107             # multipart
108             $header_params->{'Content-Type'} = lc $header_params->{'Content-Type'} eq 'multipart/form' ?
109 0 0         'form-data' : $header_params->{'Content-Type'};
110            
111 0           $_request = PUT($_url, %$header_params, Content => $_body_data);
112            
113             }
114             elsif ($method eq 'GET') {
115 0           my $headers = HTTP::Headers->new(%$header_params);
116 0           $_request = GET($_url, %$header_params);
117             }
118             elsif ($method eq 'HEAD') {
119 0           my $headers = HTTP::Headers->new(%$header_params);
120 0           $_request = HEAD($_url,%$header_params);
121             }
122             elsif ($method eq 'DELETE') { #TODO support form data
123 0           my $headers = HTTP::Headers->new(%$header_params);
124 0           $_request = DELETE($_url, %$headers, Content => $_body_data);
125             }
126             elsif ($method eq 'PATCH') { #TODO
127             }
128             else {
129             }
130            
131 0   0       $self->{ua}->timeout($self->{http_timeout} || $AsposeTasksCloud::Configuration::http_timeout);
132 0   0       $self->{ua}->agent($self->{http_user_agent} || $AsposeTasksCloud::Configuration::http_user_agent);
133            
134 0           my $_response = $self->{ua}->request($_request);
135            
136 0 0         unless ($_response->is_success) {
137 0           croak("API Exception(".$_response->code."): ".$_response->message);
138             }
139            
140 0           return $_response;
141            
142             }
143              
144             # Take value and turn it into a string suitable for inclusion in
145             # the path, by url-encoding.
146             # @param string $value a string which will be part of the path
147             # @return string the serialized object
148             sub to_path_value {
149 0     0 0   my ($self, $value) = @_;
150 0           return uri_escape($self->to_string($value));
151             }
152              
153              
154             # Take value and turn it into a string suitable for inclusion in
155             # the query, by imploding comma-separated if it's an object.
156             # If it's a string, pass through unchanged. It will be url-encoded
157             # later.
158             # @param object $object an object to be serialized to a string
159             # @return string the serialized object
160             sub to_query_value {
161 0     0 0   my ($self, $object) = @_;
162 0 0         if (is_array($object)) {
163 0           return implode(',', $object);
164             } else {
165 0           return $self->to_string($object);
166             }
167             }
168              
169              
170             # Take value and turn it into a string suitable for inclusion in
171             # the header. If it's a string, pass through unchanged
172             # If it's a datetime object, format it in ISO8601
173             # @param string $value a string which will be part of the header
174             # @return string the header string
175             sub to_header_value {
176 0     0 0   my ($self, $value) = @_;
177 0           return $self->to_string($value);
178             }
179              
180             # Take value and turn it into a string suitable for inclusion in
181             # the http body (form parameter). If it's a string, pass through unchanged
182             # If it's a datetime object, format it in ISO8601
183             # @param string $value the value of the form parameter
184             # @return string the form string
185             sub to_form_value {
186 0     0 0   my ($self, $value) = @_;
187 0           return $self->to_string($value);
188             }
189              
190             # Take value and turn it into a string suitable for inclusion in
191             # the parameter. If it's a string, pass through unchanged
192             # If it's a datetime object, format it in ISO8601
193             # @param string $value the value of the parameter
194             # @return string the header string
195             sub to_string {
196 0     0 0   my ($self, $value) = @_;
197 0 0         if (ref($value) eq "DateTime") { # datetime in ISO8601 format
198 0           return $value->datetime();
199             }
200             else {
201 0           return $value;
202             }
203             }
204              
205             # Deserialize a JSON string into an object
206             #
207             # @param string $class class name is passed as a string
208             # @param string $data data of the body
209             # @return object an instance of $class
210             sub deserialize
211             {
212 0     0 0   my ($self, $class, $data) = @_;
213 0           $log->debugf("deserializing %s for %s", $data, $class);
214            
215 0 0         if (not defined $data) {
    0          
    0          
    0          
    0          
216 0           return undef;
217             } elsif ( (substr($class, 0, 5)) eq 'HASH[') { #hash
218 0 0         if ($class =~ /^HASH\[(.*),(.*)\]$/) {
219 0           my ($key_type, $type) = ($1, $2);
220 0           my %hash;
221 0           my $decoded_data = decode_json $data;
222 0           foreach my $key (keys %$decoded_data) {
223 0 0         if (ref $decoded_data->{$key} eq 'HASH') {
224 0           $hash{$key} = $self->deserialize($type, encode_json $decoded_data->{$key});
225             } else {
226 0           $hash{$key} = $self->deserialize($type, $decoded_data->{$key});
227             }
228             }
229 0           return \%hash;
230             } else {
231             #TODO log error
232             }
233            
234             } elsif ( (substr($class, 0, 6)) eq 'ARRAY[' ) { # array of data
235 0 0         return $data if $data eq '[]'; # return if empty array
236            
237 0           my $_sub_class = substr($class, 6, -1);
238 0           my $_json_data = decode_json $data;
239 0           my @_values = ();
240 0           foreach my $_value (@$_json_data) {
241 0 0         if (ref $_value eq 'ARRAY') {
242 0           push @_values, $self->deserialize($_sub_class, encode_json $_value);
243             } else {
244 0           push @_values, $self->deserialize($_sub_class, $_value);
245             }
246             }
247 0           return \@_values;
248             } elsif ($class eq 'DateTime') {
249 0           return DateTime->from_epoch(epoch => str2time($data));
250             } elsif (grep /^$class$/, ('string', 'int', 'float', 'bool', 'object')) {
251 0           return $data;
252             } else { # model
253 0           my $_instance = use_module("AsposeTasksCloud::Object::$class")->new;
254 0 0         if (ref $data eq "HASH") {
255 0           return $_instance->from_hash($data);
256             } else { # string, need to json decode first
257 0           return $_instance->from_hash(decode_json $data);
258             }
259             }
260            
261             }
262              
263             # return 'Accept' based on an array of accept provided
264             # @param [Array] header_accept_array Array fo 'Accept'
265             # @return String Accept (e.g. application/json)
266             sub select_header_accept
267             {
268 0     0 0   my ($self, @header) = @_;
269            
270 0 0 0       if (@header == 0 || (@header == 1 && $header[0] eq '')) {
    0 0        
271 0           return undef;
272             } elsif (grep(/^application\/json$/i, @header)) {
273 0           return 'application/json';
274             } else {
275 0           return join(',', @header);
276             }
277            
278             }
279              
280             # return the content type based on an array of content-type provided
281             # @param [Array] content_type_array Array fo content-type
282             # @return String Content-Type (e.g. application/json)
283             sub select_header_content_type
284             {
285 0     0 0   my ($self, @header) = @_;
286            
287 0 0 0       if (@header == 0 || (@header == 1 && $header[0] eq '')) {
    0 0        
288 0           return 'application/json'; # default to application/json
289             } elsif (grep(/^application\/json$/i, @header)) {
290 0           return 'application/json';
291             } else {
292 0           return join(',', @header);
293             }
294            
295             }
296              
297             sub pre_deserialize
298             {
299 0     0 0   my ($self, $data, $class, $content_type) = @_;
300 0           $log->debugf("pre_deserialize %s for %s and content_type %s", $data, $class, $content_type);
301 0 0         if ($class eq "ResponseMessage") {
302 0 0 0       if (defined $content_type and lc $content_type ne 'application/json' ) {
303 0           my $_instance = use_module("AsposeTasksCloud::Object::$class")->new;
304 0           $_instance->{'Status'} = 'OK';
305 0           $_instance->{'Code'} = 200;
306 0           $_instance->{'Content'} = $data;
307 0           return $_instance;
308             }
309             }
310            
311 0 0 0       if ( (defined $content_type) && ($content_type !~ m/json/) ) {
312 0           croak("API Exception(406.): Invalid contentType".$content_type);
313             }
314            
315 0           return $self->deserialize($class, $data);
316             }
317              
318             # return signature for aspose cloud api
319             sub sign {
320 0     0 0   my ($self, $url_to_sign, $appSid, $appKey) = @_;
321            
322             #return if (!defined($url_to_sign) || scalar(@$auth_settings) == 0);
323            
324 0           my $hmac = Digest::HMAC_SHA1->new($appKey);
325 0           $hmac->add($url_to_sign);
326 0           my $signature = $hmac->digest;
327 0           $signature = encode_base64($signature, '');
328 0           $signature =~ s/=//;
329             #$signature =~ s/[^A-Za-z0-9]//g;
330 0           $log->debugf ("signature :: ".$signature);
331 0           return $signature;
332             }
333              
334             1;