File Coverage

blib/lib/Future/HTTP/Tiny.pm
Criterion Covered Total %
statement 62 83 74.7
branch 4 6 66.6
condition 1 3 33.3
subroutine 12 15 80.0
pod 5 6 83.3
total 84 113 74.3


line stmt bran cond sub pod time code
1             package Future::HTTP::Tiny;
2 6     6   241262 use strict;
  6         22  
  6         182  
3 6     6   3619 use Future;
  6         73766  
  6         189  
4 6     6   3898 use HTTP::Tiny;
  6         188453  
  6         264  
5 6     6   3390 use Moo 2; # or Moo::Lax if you can't have Moo v2
  6         69900  
  6         37  
6 6     6   9674 use Filter::signatures;
  6         18575  
  6         67  
7 6     6   165 no warnings 'experimental::signatures';
  6         12  
  6         204  
8 6     6   34 use feature 'signatures';
  6         19  
  6         4973  
9              
10             our $VERSION = '0.16';
11              
12             with 'Future::HTTP::Handler';
13              
14             has ua => (
15             is => 'lazy',
16             default => sub { HTTP::Tiny->new( %{ $_[0]->_ua_args } ) }
17             );
18              
19             has _ua_args => (
20             is => 'ro',
21             default => sub { +{} } ,
22             );
23              
24             =head1 NAME
25              
26             Future::HTTP::Tiny - synchronous HTTP client with a Future interface
27              
28             =head1 DESCRIPTION
29              
30             This is the default backend. It is chosen if no supported event loop could
31             be detected. It will execute the requests synchronously as they are
32             made in C<< ->http_request >> .
33              
34             =cut
35              
36             sub BUILDARGS {
37 1     1 0 224739 my( $class, %options ) = @_;
38              
39 1 50       14 my @ua_args = keys %options ? (_ua_args => \%options) : ();
40             return +{
41             @ua_args
42 1         27 }
43             }
44              
45 1     1 1 37 sub is_async { !1 }
46              
47 6     6   33 sub _ae_from_http_tiny( $self, $result, $url ) {
  6         17  
  6         10  
  6         12  
  6         11  
48             # Convert the result back to a future
49 6         29 my( $body ) = delete $result->{content};
50 6         17 my( $headers ) = delete $result->{headers};
51 6         30 $headers->{Status} = delete $result->{status};
52 6         21 $headers->{Reason} = delete $result->{reason};
53 6   33     29 $headers->{URL} = delete $result->{url} || $url;
54              
55             # Only filled with HTTP::Tiny 0.058+!
56 6 100       93 if( $result->{redirects}) {
57 2         7 my $r = $headers;
58 2         5 for my $http_tiny_result ( reverse @{ $result->{redirects}}) {
  2         11  
59 3         11 $r->{Redirect} = [ $self->_ae_from_http_tiny( $http_tiny_result, $url ) ];
60 3         12 $r = $r->{Redirect}->[1]; # point to the new result headers
61             };
62             };
63              
64 6         24 return ($body, $headers)
65             };
66              
67 3     3   6 sub _request($self, $method, $url, %options) {
  3         8  
  3         14  
  3         8  
  3         6  
  3         7  
68              
69             # Munge the parameters for AnyEvent::HTTP to HTTP::Tiny
70 3         24 for my $rename (
71             ['body' => 'content'],
72             ['body_cb' => 'data_callback']
73             ) {
74 6         24 my( $from, $to ) = @$rename;
75 6 50       43 if( $options{ $from }) {
76 0         0 $options{ $to } = delete $options{ $from };
77             };
78             };
79              
80             # Execute the request (synchronously)
81 3         120 my $result = $self->ua->request(
82             $method => $url,
83             \%options
84             );
85              
86 3         43291 my $res = Future->new;
87 3         61 my( $body, $headers ) = $self->_ae_from_http_tiny( $result, $url );
88 3         41 $self->http_response_received( $res, $body, $headers );
89 3         375 $res
90             }
91              
92 0     0 1 0 sub http_request($self,$method,$url,%options) {
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
93 0         0 $self->_request(
94             $method => $url,
95             %options
96             )
97             }
98              
99 3     3 1 8871 sub http_get($self,$url,%options) {
  3         17  
  3         9  
  3         13  
  3         7  
100 3         21 $self->_request(
101             'GET' => $url,
102             %options,
103             )
104             }
105              
106 0     0 1   sub http_head($self,$url,%options) {
  0            
  0            
  0            
  0            
107 0           $self->_request(
108             'HEAD' => $url,
109             %options
110             )
111             }
112              
113 0     0 1   sub http_post($self,$url,$body,%options) {
  0            
  0            
  0            
  0            
  0            
114 0           $self->_request(
115             'POST' => $url,
116             body => $body,
117             %options
118             )
119             }
120              
121             =head1 METHODS
122              
123             =head2 C<< Future::HTTP::Tiny->new() >>
124              
125             my $ua = Future::HTTP::Tiny->new();
126              
127             Creates a new instance of the HTTP client.
128              
129             =head2 C<< $ua->is_async() >>
130              
131             Returns false, because this backend is synchronous.
132              
133             =head2 C<< $ua->http_get($url, %options) >>
134              
135             $ua->http_get('http://example.com/',
136             headers => {
137             'Accept' => 'text/json',
138             },
139             )->then(sub {
140             my( $body, $headers ) = @_;
141             ...
142             });
143              
144             Retrieves the URL and returns the body and headers, like
145             the function in L.
146              
147             =head2 C<< $ua->http_head($url, %options) >>
148              
149             $ua->http_head('http://example.com/',
150             headers => {
151             'Accept' => 'text/json',
152             },
153             )->then(sub {
154             my( $body, $headers ) = @_;
155             ...
156             });
157              
158             Retrieves the header of the URL and returns the headers,
159             like the function in L.
160              
161             =head2 C<< $ua->http_post($url, $body, %options) >>
162              
163             $ua->http_post('http://example.com/api',
164             '{token:"my_json_token"}',
165             headers => {
166             'Accept' => 'text/json',
167             },
168             )->then(sub {
169             my( $body, $headers ) = @_;
170             ...
171             });
172              
173             Posts the content to the URL and returns the body and headers,
174             like the function in L.
175              
176             =head2 C<< $ua->http_request($method, $url, %options) >>
177              
178             $ua->http_request('PUT' => 'http://example.com/api',
179             headers => {
180             'Accept' => 'text/json',
181             },
182             body => '{token:"my_json_token"}',
183             )->then(sub {
184             my( $body, $headers ) = @_;
185             ...
186             });
187              
188             Posts the content to the URL and returns the body and headers,
189             like the function in L.
190              
191             =head1 COMPATIBILITY
192              
193             L is a good backend because it is distributed with many versions
194             of Perl. The drawback is that not all versions of L support all
195             features. The following features are unsupported on older versions of
196             L:
197              
198             =over 4
199              
200             =item C<< ->{URL} >>
201              
202             HTTP::Tiny versions before 0.018 didn't tell about 30x redirections.
203              
204             =item C<< ->{redirects} >>
205              
206             HTTP::Tiny versions before 0.058 didn't record the chain of redirects.
207              
208             =back
209              
210             =head1 SEE ALSO
211              
212             L
213              
214             L for the details of the API
215              
216             =head1 REPOSITORY
217              
218             The public repository of this module is
219             L.
220              
221             =head1 SUPPORT
222              
223             The public support forum of this module is
224             L.
225              
226             =head1 BUG TRACKER
227              
228             Please report bugs in this module via the RT CPAN bug queue at
229             L
230             or via mail to L.
231              
232             =head1 AUTHOR
233              
234             Max Maischein C
235              
236             =head1 COPYRIGHT (c)
237              
238             Copyright 2016-2023 by Max Maischein C.
239              
240             =head1 LICENSE
241              
242             This module is released under the same terms as Perl itself.
243              
244             =cut
245              
246             1;