File Coverage

blib/lib/App/PAIA/Agent.pm
Criterion Covered Total %
statement 55 57 96.4
branch 11 18 61.1
condition 7 12 58.3
subroutine 12 12 100.0
pod 0 7 0.0
total 85 106 80.1


line stmt bran cond sub pod time code
1             package App::PAIA::Agent;
2 4     4   13 use strict;
  4         3  
  4         89  
3 4     4   22 use v5.10;
  4         8  
  4         146  
4              
5             our $VERSION = '0.30';
6              
7 4     4   2239 use HTTP::Tiny 0.024;
  4         116923  
  4         122  
8 4     4   2029 use URI;
  4         11024  
  4         85  
9 4     4   1158 use App::PAIA::JSON;
  4         9  
  4         2005  
10              
11             sub new {
12 7     7 0 19 my ($class, %options) = @_;
13 7         57 bless {
14             insecure => !!$options{insecure},
15             logger => $options{logger},
16             dumper => $options{dumper},
17             agent => HTTP::Tiny->new( verify_SSL => (!$options{insecure}) ),
18             }, $class;
19             }
20              
21             sub request {
22 8     8 0 13 my $self = shift;
23 8         10 my $method = shift;
24 8   50     47 my $url = URI->new(shift) // '';
25 8   100     20192 my $param = shift // {};
26 8   50     60 my $headers = {
27             Accept => 'application/json',
28             'User-Agent' => "App::PAIA/".($APP::PAIA::VERSION//'?'),
29             @_
30             };
31 8         11 my $content;
32              
33 8         22 $self->{logger}->("$method $url");
34              
35 8   50     119 my $scheme = $url->scheme // '';
36 8 50       201 if ($self->{insecure}) {
    100          
37 0 0       0 return $self->error( msg => "Not an URL: $url" )
38             unless $scheme =~ /^https?$/;
39             } elsif( $scheme ne 'https' ) {
40 2         7 return $self->error(
41             msg => "PAIA requires HTTPS unless insecure (got $url)"
42             );
43             }
44              
45 6 100       17 if ($method eq 'POST') {
    50          
46 3         7 $headers->{'Content-Type'} = 'application/json';
47 3         9 $content = encode_json($param);
48             } elsif (%$param) {
49 0         0 $url->query_form(%$param);
50             }
51              
52 6         722 $self->dump_request( $method, $url, $headers, $content );
53 6         38 my $response = $self->{agent}->request( $method, $url, {
54             headers => $headers,
55             content => $content
56             } );
57              
58 6         14 $self->dump_response( $response );
59            
60 6 50       15 return $response if $response->{status} eq '599';
61              
62 6         7 my $json = eval { decode_json($response->{content}) };
  6         17  
63 6 50       13 return $self->error( url => "$url", msg => "$@" ) if "$@";
64              
65 6         37 return ($response, $json);
66             }
67              
68             sub error {
69 2     2 0 16 my ($self, %opts) = @_;
70             return {
71 2   50     38 url => $opts{url} // '',
      50        
72             success => q{},
73             status => $opts{status} // '599',
74             reason => 'Internal Exception',
75             content => $opts{msg},
76             headers => {
77             'content-type' => 'text/plain',
78             'content-length' => length $opts{msg},
79             }
80             };
81             }
82              
83             sub dump {
84 52     52 0 243 my ($self, $msg) = @_;
85             # say ":$msg";
86 52         72 $self->{dumper}->($msg);
87             }
88              
89             sub dump_request {
90 6     6 0 11 my ($self, $method, $url, $headers, $content) = @_;
91              
92 6         32 $self->dump("$method " . $url->path_query ." HTTP/1.1");
93 6         17 $self->dump("Host: " . $url->host);
94 6         17 $self->dump_message( $headers, $content );
95             }
96              
97             sub dump_response {
98 6     6 0 8 my ($self, $res) = @_;
99              
100 6         16 $self->dump("\n" . $res->{protocol} . " " . $res->{status});
101 6         9 $self->dump_message( $res->{headers}, $res->{content} );
102             }
103              
104             sub dump_message {
105 12     12 0 13 my ($self, $headers, $content) = @_;
106              
107 12         9 while (my ($header, $value) = each %{$headers}) {
  37         74  
108 25 50       32 $value = join ", ", @$value if ref $value;
109 25         41 $self->dump(ucfirst($header) . ": $value");
110             }
111 12 100       34 $self->dump("\n$content") if defined $content;
112             }
113              
114             1;
115             __END__