File Coverage

blib/lib/Net/Async/Webservice/Common/WithRequestWrapper.pm
Criterion Covered Total %
statement 48 48 100.0
branch 5 6 83.3
condition 6 9 66.6
subroutine 16 16 100.0
pod 3 3 100.0
total 78 82 95.1


line stmt bran cond sub pod time code
1             package Net::Async::Webservice::Common::WithRequestWrapper;
2             $Net::Async::Webservice::Common::WithRequestWrapper::VERSION = '1.0.2';
3             {
4             $Net::Async::Webservice::Common::WithRequestWrapper::DIST = 'Net-Async-Webservice-Common';
5             }
6 1     1   289219 use Moo::Role;
  1         3  
  1         14  
7 1     1   359431 use Types::Standard qw(Object HashRef Str);
  1         84451  
  1         15  
8 1     1   1786 use Types::URI qw(Uri);
  1         1463241  
  1         21  
9 1     1   10470 use Type::Params qw(compile);
  1         14496  
  1         12  
10 1     1   4127 use Net::Async::Webservice::Common::Types qw(HTTPRequest);
  1         5  
  1         16  
11 1     1   1464 use Net::Async::Webservice::Common::Exception;
  1         4  
  1         37  
12 1     1   9 use HTTP::Request;
  1         1  
  1         26  
13 1     1   1398 use Encode;
  1         13846  
  1         119  
14 1     1   13 use namespace::autoclean;
  1         4  
  1         12  
15 1     1   115 use 5.010;
  1         3  
  1         623  
16              
17             # ABSTRACT: helper methods to perform HTTP request
18              
19              
20             requires 'user_agent';
21              
22              
23             has ssl_options => (
24             is => 'lazy',
25             isa => HashRef,
26             );
27             sub _build_ssl_options {
28             # this is to work around an issue with IO::Async::SSL, see
29             # https://rt.cpan.org/Ticket/Display.html?id=96474
30 1 50   1   852 eval "require IO::Socket::SSL" or return {};
31 1         27 return { SSL_verify_mode => IO::Socket::SSL::SSL_VERIFY_PEER() }
32             }
33              
34              
35             sub request {
36 5     5 1 15752 state $argcheck = compile( Object, HTTPRequest );
37 5         2904 my ($self, $request) = $argcheck->(@_);
38              
39 2   50     83 my $response_future = $self->user_agent->do_request(
40             request => $request,
41             fail_on_error => 1,
42             (($request->uri->scheme//'') eq 'https' ? %{ $self->ssl_options // {} } : ()),
43             )->transform(
44             done => sub {
45 3     3   869 my ($response) = @_;
46 3         35 return $response->decoded_content(
47             default_charset => 'utf-8',
48             raise_error => 1,
49             )
50             },
51             fail => sub {
52 2     2   463 my ($exception,$kind,$response,$req2) = @_;
53 2 100 33     98 return (Net::Async::Webservice::Common::Exception::HTTPError->new({
      100        
54             request=>($req2//$request),
55             response=>$response,
56             (($kind//'') ne 'http' ? ( more_info => "@_" ) : ()),
57             }),'webservice');
58             },
59 5 100 100     123 );
60             }
61              
62              
63             sub post {
64 1     1 1 27015 state $argcheck = compile( Object, Uri, Str );
65 1         1731 my ($self, $url, $body) = $argcheck->(@_);
66              
67 1         110 my $request = HTTP::Request->new(
68             POST => $url,
69             [], encode('utf-8',$body),
70             );
71 1         484 return $self->request($request);
72             }
73              
74              
75             sub get {
76 3     3 1 271504 state $argcheck = compile( Object, Uri );
77 3         9399 my ($self, $url) = $argcheck->(@_);
78              
79 3         11600 my $request = HTTP::Request->new(
80             GET => $url,
81             );
82 3         833 return $self->request($request);
83             }
84              
85             1;
86              
87             __END__
88              
89             =pod
90              
91             =encoding UTF-8
92              
93             =head1 NAME
94              
95             Net::Async::Webservice::Common::WithRequestWrapper - helper methods to perform HTTP request
96              
97             =head1 VERSION
98              
99             version 1.0.2
100              
101             =head1 SYNOPSIS
102              
103             package My::WS::Client {
104             use Moo;
105             with 'Net::Async::Webservice::Common::WithUserAgent';
106             with 'Net::Async::Webservice::Common::WithRequestWrapper';
107             }
108              
109             my $loop = IO::Async::Loop->new;
110             my $c = My::WS::Client->new({loop=>$loop});
111             $c->post('https://api.webservice.whatever/',$content)->then(sub{
112             my ($response_body) = @_;
113             say "Got <$response_body>";
114             return Future->wrap();
115             })->get;
116              
117             =head1 DESCRIPTION
118              
119             This role provides a few methods to perform HTTP requests via a
120             C<user_agent> attribute / method (which is required, and could be
121             provided by L<Net::Async::Webservice::Common::WithUserAgent> or any
122             other means).
123              
124             Failures (both during connection, and as signaled by the HTTP response
125             codes) are wrapped in
126             L<Net::Async::Webservice::Common::Exception::HTTPError> and returned
127             as failed futures. On success, the future yields the decoded content
128             of the response.
129              
130             =head1 ATTRIBUTES
131              
132             =head2 C<ssl_options>
133              
134             Optional hashref, its contents will be passed to C<user_agent>'s
135             C<do_request> method.
136              
137             =head1 METHODS
138              
139             =head2 C<request>
140              
141             $c->request($http_request) ==> $decoded_content
142              
143             Performs the given request via the C<user_agent>, with
144             C<fail_on_error> set; if the request succeeds, the returned future
145             will yield the decoded content of the response. If the request fails,
146             the future will fail with a two-element failure: a
147             L<Net::Async::Webservice::Common::Exception::HTTPError> and the string
148             C<'webservice'>.
149              
150             =head2 C<post>
151              
152             $c->post($url,$body) ==> $decoded_content
153              
154             Shortcut to submit a very basic POST request. The C<$body> will be
155             UTF-8 encoded, no headers are set. Uses L</request> to perform the
156             actual request.
157              
158             =head2 C<get>
159              
160             $c->get($url) ==> $decoded_content
161              
162             Shortcut to submit a very basic GET request. No headers are set. Uses
163             L</request> to perform the actual request.
164              
165             =head1 AUTHOR
166              
167             Gianni Ceccarelli <gianni.ceccarelli@net-a-porter.com>
168              
169             =head1 COPYRIGHT AND LICENSE
170              
171             This software is copyright (c) 2014 by Net-a-porter.com.
172              
173             This is free software; you can redistribute it and/or modify it under
174             the same terms as the Perl 5 programming language system itself.
175              
176             =cut