File Coverage

blib/lib/AnyEvent/HTTP/ScopedClient.pm
Criterion Covered Total %
statement 1 3 33.3
branch n/a
condition n/a
subroutine 1 1 100.0
pod n/a
total 2 4 50.0


line stmt bran cond sub pod time code
1             package AnyEvent::HTTP::ScopedClient;
2             {
3             $AnyEvent::HTTP::ScopedClient::VERSION = '0.0.5';
4             }
5              
6             # ABSTRACT: L<AnyEvent> based L<https://github.com/technoweenie/node-scoped-http-client>
7              
8 2     2   121468 use Moose;
  0            
  0            
9             use namespace::autoclean;
10              
11             use URI;
12             use Try::Tiny;
13             use MIME::Base64;
14             use HTTP::Request;
15             use Encode qw/encode_utf8/;
16             use AnyEvent::HTTP;
17             use URI::QueryParam;
18             use URI::Escape;
19              
20             has 'options' => (
21             is => 'ro',
22             isa => 'HashRef',
23             );
24              
25             sub request {
26             my ( $self, $method, $reqBody, $callback ) = @_;
27             if ( 'CODE' eq ref($reqBody) ) {
28             $callback = $reqBody;
29             undef $reqBody;
30             }
31              
32             my %options = %{ $self->options };
33             try {
34             my %headers = %{ $options{headers} };
35              
36             if ( 'HASH' eq ref($reqBody) ) {
37             my @pair;
38              
39             # push @pair, "$_=$reqBody->{$_}" for ( keys %$reqBody );
40             push @pair, "$_=" . uri_escape_utf8( $reqBody->{$_} )
41             for ( keys %$reqBody );
42             $reqBody = join( '&', @pair );
43             }
44              
45             my $sendingData
46             = ( $method =~ m/^P/ && $reqBody && length $reqBody > 0 ) ? 1 : 0;
47             $headers{'Content-Length'} = length $reqBody if $sendingData;
48             $headers{'Content-Type'} = 'application/x-www-form-urlencoded'
49             if ( $sendingData && !$headers{'Content-Type'} );
50              
51             if ( $options{auth} ) {
52             $headers{Authorization}
53             = 'Basic ' . encode_base64( $options{auth}, '' );
54             }
55              
56             if ( $ENV{DEBUG} ) {
57             print "$method " . $self->options->{url} . "\n";
58             while ( my ( $k, $v ) = each %headers ) {
59             print "$k: $v\n";
60             }
61              
62             print "\n";
63             print "$reqBody\n" if $sendingData;
64             }
65              
66             http_request(
67             $method,
68             $options{url},
69             headers => \%headers,
70             body => $sendingData ? encode_utf8($reqBody) : undef,
71             $callback
72             );
73             }
74             catch {
75             $callback->($_) if $callback;
76             };
77              
78             return $self;
79             }
80              
81             sub fullPath {
82             my ( $self, $p ) = @_;
83             }
84              
85             sub scope {
86             my ( $self, $url, $options, $callback ) = @_;
87             }
88              
89             sub join {
90             my ( $self, $suffix ) = @_;
91             }
92              
93             sub path {
94             my ( $self, $p ) = @_;
95             }
96              
97             sub query {
98             my ( $self, $key, $value ) = @_;
99             if ( 'HASH' eq ref $key ) {
100             while ( my ( $k, $v ) = each %$key ) {
101             $self->options->{url}->query_param( $k => $v );
102             }
103             }
104             else {
105             $self->options->{url}->query_param( $key => $value );
106             }
107             return $self;
108             }
109              
110             sub host {
111             my ( $self, $h ) = @_;
112             }
113              
114             sub protocol {
115             my ( $self, $p ) = @_;
116             }
117              
118             sub auth {
119             my ( $self, $user, $pass ) = @_;
120             if ( !$user ) {
121             $self->options->{auth} = undef;
122             }
123             elsif ( !$pass && $user =~ m/:/ ) {
124             $self->options->{auth} = $user;
125             }
126             else {
127             $self->options->{auth} = "$user:$pass";
128             }
129              
130             return $self;
131             }
132              
133             sub header {
134             my ( $self, $name, $value ) = @_;
135             if ( 'HASH' eq ref $name ) {
136             while ( my ( $k, $v ) = each %$name ) {
137             $self->options->{headers}{$k} = $v;
138             }
139             }
140             else {
141             $self->options->{headers}{$name} = $value;
142             }
143              
144             return $self;
145             }
146              
147             sub headers {
148             my ( $self, $h ) = @_;
149             }
150              
151             sub buildOptions {
152             my ( $self, $url, $params ) = @_;
153             $params->{options}{url} = URI->new($url);
154             $params->{options}{headers} ||= {};
155             }
156              
157             sub BUILDARGS {
158             my ( $self, $url, %params ) = @_;
159             $self->buildOptions( $url, \%params );
160             return \%params;
161             }
162              
163             sub get { shift->request( 'GET', @_ ) }
164             sub post { shift->request( 'POST', @_ ) }
165             sub patch { shift->request( 'PATCH', @_ ) }
166             sub put { shift->request( 'PUT', @_ ) }
167             sub delete { shift->request( 'DELETE', @_ ) }
168             sub head { shift->request( 'HEAD', @_ ) }
169              
170             __PACKAGE__->meta->make_immutable;
171              
172             1;
173              
174             __END__
175              
176             =pod
177              
178             =encoding utf-8
179              
180             =head1 NAME
181              
182             AnyEvent::HTTP::ScopedClient - L<AnyEvent> based L<https://github.com/technoweenie/node-scoped-http-client>
183              
184             =head1 VERSION
185              
186             version 0.0.5
187              
188             =head1 SYNOPSIS
189              
190             my $client = AnyEvent::HTTP::ScopedClient->new('http://example.com');
191             $client->request('GET', sub {
192             my ($body, $hdr) = @_; # $body is undef if error occured
193             return if ( !$body || $hdr->{Status} !~ /^2/ );
194             # do something;
195             });
196              
197             # shorcut for GET
198             $client->get(sub {
199             my ($body, $hdr) = @_;
200             # ...
201             });
202              
203             # Content-Type: application/x-www-form-urlencoded
204             $client->post(
205             { foo => 1, bar => 2 }, # note this.
206             sub {
207             my ($body, $hdr) = @_;
208             # ...
209             }
210             );
211              
212             # application/x-www-form-urlencoded post request
213             $client->post(
214             "foo=1&bar=2" # and note this.
215             sub {
216             my ($body, $hdr) = @_;
217             # ...
218             }
219             );
220              
221             # Content-Type: application/json
222             use JSON::XS;
223             $client->header('Content-Type', 'application/json')
224             ->post(
225             encode_json({ foo => 1 }),
226             sub {
227             my ($body, $hdr) = @_;
228             # ...
229             }
230             );
231              
232             $client->header('Accept', 'application/json')
233             ->query({ key => 'value' })
234             ->query('key', 'value')
235             ->get(
236             sub {
237             my ($body, $hdr) = @_;
238             # ...
239             }
240             );
241              
242             # headers at once
243             $client->header({
244             Accept => '*/*',
245             Authorization => 'Basic abcd'
246             })->get(
247             sub {
248             my ($body, $hdr) = @_;
249             # ...
250             }
251             );
252              
253             =head1 DESCRIPTION
254              
255             L<AnyEvent::HTTP> wrapper
256              
257             =head1 SEE ALSO
258              
259             L<https://github.com/technoweenie/node-scoped-http-client>
260              
261             =head1 AUTHOR
262              
263             Hyungsuk Hong <hshong@perl.kr>
264              
265             =head1 COPYRIGHT AND LICENSE
266              
267             This software is copyright (c) 2012 by Hyungsuk Hong.
268              
269             This is free software; you can redistribute it and/or modify it under
270             the same terms as the Perl 5 programming language system itself.
271              
272             =cut