File Coverage

blib/lib/API/Client/Core.pm
Criterion Covered Total %
statement 21 21 100.0
branch n/a
condition n/a
subroutine 7 8 87.5
pod n/a
total 28 29 96.5


line stmt bran cond sub pod time code
1             # Client Core Class
2             package API::Client::Core;
3              
4 1     1   695 use Data::Object::Class;
  1         3  
  1         9  
5 1     1   296 use Data::Object::Signatures;
  1         2  
  1         7  
6              
7 1         5 use Data::Object::Library qw(
8             InstanceOf
9             Int
10 1     1   7966 );
  1         2  
11              
12 1     1   1752 use Mojo::Transaction;
  1         144546  
  1         10  
13 1     1   901 use Mojo::UserAgent;
  1         94843  
  1         9  
14 1     1   39 use Mojo::URL;
  1         2  
  1         4  
15              
16 1     1   639 use API::Client::Exception;
  1         4  
  1         220  
17              
18             our $VERSION = '0.03'; # VERSION
19              
20             # ATTRIBUTES
21              
22             has debug => (
23             is => 'rw',
24             isa => Int,
25             default => 0,
26             required => 0,
27             );
28              
29             has fatal => (
30             is => 'rw',
31             isa => Int,
32             default => 0,
33             required => 0,
34             );
35              
36             has retries => (
37             is => 'rw',
38             isa => Int,
39             default => 0,
40             required => 0,
41             );
42              
43             has timeout => (
44             is => 'rw',
45             isa => Int,
46             default => 10,
47             required => 0,
48             );
49              
50             has url => (
51             is => 'ro',
52             isa => InstanceOf['Mojo::URL'],
53             coerce => fun { ref($_[0]) ? $_[0] : Mojo::URL->new($_[0]) },
54             required => 0,
55             );
56              
57             has user_agent => (
58             is => 'ro',
59             isa => InstanceOf['Mojo::UserAgent'],
60             default => fun { Mojo::UserAgent->new },
61             required => 0,
62             );
63              
64             # DELEGATES
65              
66             my @methods = qw(
67             DELETE
68             GET
69             HEAD
70             OPTIONS
71             PATCH
72             POST
73             PUT
74             );
75              
76             around [@methods] => fun ($orig, $self, %args) {
77              
78             my $retries = $self->retries;
79             my $ua = $self->user_agent;
80              
81             # client timeouts
82             $ua->max_redirects(0);
83             $ua->connect_timeout($self->timeout);
84             $ua->request_timeout($self->timeout);
85              
86             # request initialization
87             $ua->on(start => fun ($ua, $tx) {
88              
89             $self->PREPARE($ua, $tx, %args);
90              
91             });
92              
93             # retry entry point
94             RETRY:
95              
96             # execute transaction
97             my $tx = $self->$orig(%args);
98              
99             # fetch transaction objects
100             my $req = $tx->req;
101             my $res = $tx->res;
102              
103             # determine success/failure
104             my $ok = $res->code ? $res->code !~ /(4|5)\d\d/ : 0;
105              
106             # attempt logging where applicable
107             if ($req and $res and $self->debug) {
108              
109             my $reqstr = $req->to_string;
110             my $resstr = $res->to_string;
111              
112             $reqstr =~ s/\s*$/\n\n\n/;
113             $resstr =~ s/\s*$/\n\n\n/;
114              
115             print STDOUT $reqstr;
116             print STDOUT $resstr;
117              
118             }
119              
120             # retry transaction where applicable
121             goto RETRY if $retries-- > 0 and not $ok;
122              
123             # throw exception if fatal is enabled
124             if ($req and $res and $self->fatal and not $ok) {
125              
126             API::Client::Exception->throw(
127             tx => $tx,
128             code => $res->code,
129             method => $req->method,
130             url => $req->url,
131             );
132              
133             }
134              
135             # return JSON
136             return $res->json;
137              
138             };
139              
140             # METHODS
141              
142             method DELETE (Str :$path = '', HashRef :$data = {}, HashRef :$query = {}) {
143              
144             my $ua = $self->user_agent;
145             my $url = $self->url->clone;
146              
147             $url->path(join '/', $url->path, $path) if $path;
148             $url->query($url->query->merge(%$query)) if keys %$query;
149              
150             return $ua->delete($url, ({}, keys(%$data) ? (json => $data) : ()));
151              
152             }
153              
154       0     fun DESTROY {
155              
156             ; # Protect subclasses using AUTOLOAD
157              
158             }
159              
160             method GET (Str :$path = '', HashRef :$data = {}, HashRef :$query = {}) {
161              
162             my $ua = $self->user_agent;
163             my $url = $self->url->clone;
164              
165             $url->path(join '/', $url->path, $path) if $path;
166             $url->query($url->query->merge(%$query)) if keys %$query;
167              
168             return $ua->get($url, ({}, keys(%$data) ? (json => $data) : ()));
169              
170             }
171              
172             method HEAD (Str :$path = '', HashRef :$data = {}, HashRef :$query = {}) {
173              
174             my $url = $self->url->clone;
175             my $ua = $self->user_agent;
176              
177             $url->path(join '/', $url->path, $path) if $path;
178             $url->query($url->query->merge(%$query)) if keys %$query;
179              
180             return $ua->head($url, ({}, keys(%$data) ? (json => $data) : ()));
181              
182             }
183              
184             method OPTIONS (Str :$path = '', HashRef :$data = {}, HashRef :$query = {}) {
185              
186             my $url = $self->url->clone;
187             my $ua = $self->user_agent;
188              
189             $url->path(join '/', $url->path, $path) if $path;
190             $url->query($url->query->merge(%$query)) if keys %$query;
191              
192             return $ua->options($url, ({}, keys(%$data) ? (json => $data) : ()));
193              
194             }
195              
196             method PATCH (Str :$path = '', HashRef :$data = {}, HashRef :$query = {}) {
197              
198             my $url = $self->url->clone;
199             my $ua = $self->user_agent;
200              
201             $url->path(join '/', $url->path, $path) if $path;
202             $url->query($url->query->merge(%$query)) if keys %$query;
203              
204             return $ua->patch($url, ({}, keys(%$data) ? (json => $data) : ()));
205              
206             }
207              
208             method POST (Str :$path = '', HashRef :$data = {}, HashRef :$query = {}) {
209              
210             my $url = $self->url->clone;
211             my $ua = $self->user_agent;
212              
213             $url->path(join '/', $url->path, $path) if $path;
214             $url->query($url->query->merge(%$query)) if keys %$query;
215              
216             return $ua->post($url, ({}, keys(%$data) ? (json => $data) : ()));
217              
218             }
219              
220             method PUT (Str :$path = '', HashRef :$data = {}, HashRef :$query = {}) {
221              
222             my $url = $self->url->clone;
223             my $ua = $self->user_agent;
224              
225             $url->path(join '/', $url->path, $path) if $path;
226             $url->query($url->query->merge(%$query)) if keys %$query;
227              
228             return $ua->put($url, ({}, keys(%$data) ? (json => $data) : ()));
229              
230             }
231              
232             1;