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