File Coverage

blib/lib/WWW/Giraffi/API/Request.pm
Criterion Covered Total %
statement 27 101 26.7
branch 0 20 0.0
condition 0 16 0.0
subroutine 9 24 37.5
pod 7 7 100.0
total 43 168 25.6


line stmt bran cond sub pod time code
1             package WWW::Giraffi::API::Request;
2              
3 2     2   3602 use strict;
  2         5  
  2         84  
4 2     2   76 use warnings;
  2         5  
  2         69  
5 2     2   28 use 5.10.0;
  2         8  
  2         187  
6             use Class::XSAccessor
7 2         38 constructor => "new",
8             accessors => {
9             apikey => "apikey",
10             agent => "agent",
11             ssl_verify_hostname => "ssl_verify_hostname",
12             use_time_piece => "use_time_piece",
13             timeout => "timeout",
14             default_endpoint => "default_endpoint",
15             applogs_endpoint => "applogs_endpoint",
16             monitoringdata_endpoint => "monitoringdata_endpoint",
17             verbose => "verbose",
18             last_request => "last_request",
19             last_response => "last_response",
20             },
21             #true => [qw(verbose)],
22 2     2   1916 replace => 1;
  2         6003  
23 2     2   3588 use JSON::Any;
  2         104081  
  2         14  
24 2     2   25103 use LWP::UserAgent;
  2         375433  
  2         88  
25 2     2   23 use HTTP::Request;
  2         5  
  2         49  
26 2     2   11 use HTTP::Response;
  2         3  
  2         39  
27 2     2   11 use URI;
  2         5  
  2         3436  
28              
29             our $VERSION = '0.2_04';
30             our %REQUEST_HEADERS = (
31             "Accept" => "application/json",
32             "Content-Type" => "application/json"
33             );
34             our $CLIENT_TIMEOUT_DELAY = 2;
35             our $CLIENT_TIMEOUT_CODE = 408;
36              
37             #has apikey => ( is => "rw", isa => "Str" );
38             #has agent => ( is => "rw", isa => "Str" );
39             #has ssl_verify_hostname => ( is => "rw", isa => "Num");
40             #has timeout => ( is => "rw", isa => "Num" );
41             #has default_endpoint => ( is => "rw", isa => "Str" );
42             #has applogs_endpoint => ( is => "rw", isa => "Str" );
43             #has monitoringdata_endpoint => ( is => "rw", isa => "Str" );
44             #has verbose => ( is => "rw", isa => "Num" );
45              
46             sub get {
47              
48 0     0 1   my ( $self, $path_or_uri, $queryref, $other_options ) = @_;
49 0           my $res = $self->request( "GET", $path_or_uri, $queryref, undef, $other_options );
50             #return $self->_json2ref( $res->content );
51 0           return $self->_response2ref( $res );
52             }
53              
54             sub post {
55              
56 0     0 1   my ( $self, $path_or_uri, $queryref, $contentref, $other_options ) = @_;
57 0           my $res = $self->request( "POST", $path_or_uri, $queryref, $contentref, $other_options );
58             #return $self->_json2ref( $res->content );
59 0           return $self->_response2ref( $res );
60             }
61              
62             sub put {
63              
64 0     0 1   my ( $self, $path_or_uri, $queryref, $contentref, $other_options ) = @_;
65 0           my $res = $self->request( "PUT", $path_or_uri, $queryref, $contentref, $other_options );
66             #return $self->_json2ref( $res->content );
67 0           return $self->_response2ref( $res );
68             }
69              
70             sub delete {
71              
72 0     0 1   my ( $self, $path_or_uri, $queryref, $contentref, $other_options ) = @_;
73 0           my $res = $self->request( "DELETE", $path_or_uri, $queryref, $contentref, $other_options );
74             #return $self->_json2ref( $res->content );
75 0           return $self->_response2ref( $res );
76             }
77              
78             sub request {
79              
80 0     0 1   my ( $self, $method, $path_or_uri, $queryref, $contentref, $other_options ) = @_;
81 0           my $req = $self->make_request( $method, $path_or_uri, $queryref, $contentref, $other_options );
82 0           return $self->_request($req);
83             }
84              
85             sub _request {
86              
87 0     0     my($self, $req) = @_;
88              
89 0           my $ua = LWP::UserAgent->new( agent => $self->agent, timeout => $self->timeout );
90 0 0         if ( !$self->ssl_verify_hostname ) {
91 0           $ua->ssl_opts( verify_hostname => 0 );
92             }
93 0           $self->_verbose( sprintf "request request_line %s => %s", $req->method, $req->uri );
94 0 0         if ($req->content) {
95 0           $self->_verbose( sprintf "request content => %s", $req->content );
96             }
97              
98 0           my $res;
99             my $is_client_timeout;
100 0           eval {
101 0     0     local $SIG{ALRM} = sub { $is_client_timeout = 1 };
  0            
102 0           alarm $self->timeout + $CLIENT_TIMEOUT_DELAY;
103 0           $self->last_request($req);
104 0           $res = $ua->request($req);
105 0           alarm 0;
106             };
107 0 0         if ($is_client_timeout) {
108 0           $res = $self->make_response( $CLIENT_TIMEOUT_CODE, { error => "alarm timeout" } );
109             }
110 0           $self->last_response($res);
111              
112 0           $self->_verbose( sprintf "response status_line => %s", $res->status_line );
113              
114 0           return $res;
115             }
116              
117             sub make_request {
118              
119 0     0 1   my($self, $method, $path_or_uri, $queryref, $contentref, $other_options) = @_;
120 0           my $req = HTTP::Request->new( $method => $self->_make_uri( $path_or_uri, $queryref, $other_options ) );
121 0 0 0       if ( $req->method =~ /^(POST|PUT|DELETE)$/ && ref($contentref) =~ /^(ARRAY|HASH)$/ ) {
122 0           $req->header(%REQUEST_HEADERS);
123 0           $req->content( $self->_ref2json($contentref) );
124             }
125 0           return $req;
126             }
127              
128             sub make_response {
129              
130 0     0 1   my ( $self, $code, $message, $json ) = @_;
131 0   0       $json //= $self->_ref2json($message);
132 0           return HTTP::Response->new( $code, $message, [ "Content-Type" => "application/json" ], $json );
133             }
134              
135             sub _json2ref {
136              
137 0     0     my ( $self, $json ) = @_;
138             #my $ref;
139             #eval {
140             # $ref = JSON::Any->new->decode($json);
141             #};
142             #if ($@) {
143             # $ref = JSON::Any->new->decode("{'error':'$json'}");
144             #}
145             #return $ref;
146 0           return JSON::Any->new->decode($json);
147             }
148              
149             sub _ref2json {
150              
151 0     0     my ( $self, $ref ) = @_;
152             #my $json;
153             #eval {
154             # $json = JSON::Any->new->encode($ref);
155             #};
156             #if ($@) {
157             # $json = JSON::Any->new->encode({ error => $ref });
158             #}
159             #return $json;
160 0           return JSON::Any->new->encode($ref);
161             }
162              
163             sub _response2ref {
164              
165 0     0     my( $self, $res ) = @_;
166 0           my $ref;
167 0 0         if ($self->_is_json($res->content)) {
168 0           $ref = $self->_json2ref($res->content);
169             } else {
170 0 0         if ($res->code =~ /^2\d{2}$/) { # if normal http success code
171 0           $ref = { content => $res->content };
172             } else {
173 0           $ref = { error => $res->status_line };
174             }
175             }
176              
177 0           return $ref;
178             }
179              
180             sub _is_json {
181              
182 0     0     my($self, $json) = @_;
183 0 0 0       return ($json =~ /^\{.*\}$/ or $json =~ /^\[.*\]$/) ? 1 : 0;
184             }
185              
186             sub _verbose {
187              
188 0     0     my ( $self, $message ) = @_;
189 0 0         return if !$self->verbose;
190 0           warn "VERBOSE: $message\n";
191             }
192              
193             sub _make_uri {
194              
195 0     0     my ( $self, $path_or_uri, $queryref, $other_options ) = @_;
196              
197 0   0       $path_or_uri //= "";
198 0   0       $queryref //= {};
199 0 0         if ($path_or_uri !~ /^https?:\/\//) {
200 0           $path_or_uri = sprintf "%s/%s", $self->default_endpoint, $path_or_uri;
201             }
202              
203 0           my $apikey;
204 0 0 0       if (ref($other_options) eq "HASH" && exists $other_options->{apikey}) {
205 0           $apikey = $other_options->{apikey};
206             } else {
207 0           $apikey = $self->apikey;
208             }
209              
210 0           my $uri = URI->new($path_or_uri);
211 0           $uri->query_form( [ apikey => $apikey, %{$queryref} ] );
  0            
212 0           return $uri;
213             }
214              
215             1;
216             __END__