File Coverage

blib/lib/WWW/Marvel/Client.pm
Criterion Covered Total %
statement 54 80 67.5
branch 8 18 44.4
condition 4 18 22.2
subroutine 16 21 76.1
pod 0 15 0.0
total 82 152 53.9


line stmt bran cond sub pod time code
1             package WWW::Marvel::Client;
2 2     2   18090 use Carp;
  2         4  
  2         139  
3 2     2   8 use Digest::MD5;
  2         2  
  2         52  
4 2     2   625 use JSON;
  2         11162  
  2         8  
5 2     2   1482 use LWP::UserAgent;
  2         70385  
  2         75  
6 2     2   18 use URI;
  2         6  
  2         1494  
7              
8             sub new {
9 1     1 0 11 my ($class, $args) = @_;
10 1         2 my $self = bless {}, $class;
11 1         2 for my $k (qw/ private_key public_key /) {
12 2 50       10 $self->{$k} = $args->{$k} if exists $args->{$k};
13             }
14 1         3 return $self;
15             }
16              
17 3     3 0 8 sub get_private_key { $_[0]->{private_key} }
18 4     4 0 15 sub get_public_key { $_[0]->{public_key} }
19 4     4 0 15 sub get_timestamp { $_[0]->{timestamp} }
20             sub set_timestamp {
21 1     1 0 4 my ($self, $timestamp) = @_;
22 1         2 $self->{timestamp} = $timestamp;
23 1         2 return $self;
24             }
25              
26 1     1 0 6 sub get_endpoint { "http://gateway.marvel.com" }
27 1     1 0 9 sub get_api_version { "v1" }
28              
29             sub auth_query_params {
30 1     1 0 2 my ($self) = @_;
31              
32 1   33     2 my $time = $self->get_timestamp || time;
33              
34 1         3 my %params = (
35             ts => $time,
36             apikey => $self->get_public_key,
37             hash => $self->hash($time),
38             );
39 1         3 return \%params;
40             }
41              
42             sub characters {
43 0     0 0 0 my ($self, $params) = @_;
44 0         0 my %p = %$params;
45 0         0 my $uri = $self->uri({ path => 'characters', params => \%p });
46 0         0 my $http_res = $self->get($uri);
47 0         0 return $self->_get_json_content($http_res);
48             }
49              
50             sub get {
51 0     0 0 0 my ($self, $uri) = @_;
52 0         0 my $attempts_limit = 3;
53 0         0 my $http_res;
54 0         0 while ($attempts_limit > 0) {
55 0         0 $http_res = $self->ua->get($uri);
56 0 0       0 last if $http_res->is_success;
57              
58 0         0 carp sprintf("Status line: '%s'", $http_res->status_line);
59 0         0 $attempts_limit--;
60 0 0 0     0 next if $attempts_limit && $http_res->status_line eq "500 read timeout";
61              
62 0         0 croak sprintf("Status line: '%s'\nReq: %s\nRes: %s",
63             $http_res->status_line,
64             $http_res->request->as_string,
65             $http_res->as_string);
66             }
67              
68 0         0 return $http_res;
69             }
70              
71             # ref: https://developer.marvel.com/documentation/authorization
72             sub hash {
73 3     3 0 6 my ($self, $time) = @_;
74              
75 3 100       8 if (!defined $time) {
76 1 50       2 croak "need a timestamp to create a md5 hash" if !defined $self->get_timestamp;
77 1         3 $time = $self->get_timestamp;
78             }
79              
80 3         16 my $md5 = Digest::MD5->new;
81 3         8 $md5->add( $time, $self->get_private_key, $self->get_public_key );
82 3         24 return $md5->hexdigest;
83             }
84              
85             sub _get_json_content {
86 0     0   0 my ($self, $http_res) = @_;
87 0         0 my $content = $self->json->decode( $http_res->decoded_content );
88 0         0 return $content;
89             }
90              
91 0   0 0 0 0 sub json { $_[0]->{_json} //= do { JSON->new()->allow_nonref->relaxed } }
  0         0  
92              
93 0     0 0 0 sub ua { LWP::UserAgent->new() }
94              
95             sub uri {
96 1     1 0 3 my ($self, $args) = @_;
97              
98              
99 1         1 my @paths;
100 1 50 33     12 if (exists $args->{path} && ref $args->{path} eq 'ARRAY') {
    50 33        
101 0         0 @paths = @{ $args->{path} };
  0         0  
102             }
103             elsif (exists $args->{path} && ref $args->{path} eq '') {
104 1         3 push(@paths, $args->{path});
105             }
106              
107 1         1 my %params;
108 1 50 33     3 if (exists $args->{params} && ref $args->{params} eq 'HASH') {
109 0         0 %params = %{ $args->{params} };
  0         0  
110             }
111              
112              
113 1         5 my $auth_query_params = $self->auth_query_params;
114 1         4 my %query_params = ( %params, %$auth_query_params );
115              
116 1         3 my $uri = URI->new( $self->get_endpoint );
117 1         7329 $uri->path( $self->uri_path(@paths) );
118 1         143 $uri->query_form(%query_params);
119              
120 1         90 return $uri;
121             }
122              
123             sub uri_path {
124 1     1 0 3 my ($self, @resources) = @_;
125 1 50       4 croak "need a resource to query" if @resources < 1;
126 1         3 return join('/', $self->get_api_version, 'public', @resources );
127             }
128              
129             1;