Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: rwstauner/AnyEvent-HTTP-Message
base: 2271b13fdd
...
head fork: rwstauner/AnyEvent-HTTP-Message
compare: ce46d4433b
  • 5 commits
  • 5 files changed
  • 0 commit comments
  • 1 contributor
View
13 Changes
@@ -2,9 +2,20 @@ Revision history for AnyEvent-HTTP-Message
{{$NEXT}}
+ [Backwards Incompatible Changes]
+ - For consistency/clarity/simplicity $request->params
+ no longer includes 'body' and 'headers'. Use the accessor methods.
+ 'params' is now only used for the extra AnyEvent::HTTP (user-agent) params.
+ - $request->body will default to an empty string if not defined.
+
+ [Enhancements]
+ - Enable conversion from/to HTTP::Message objects
+
+ [Fixes]
- Fix error messages when parse_args gets the wrong number of arguments.
- - Fix module name copy/paste error in Response Synopsis pod
+ [Documentation]
+ - Reorganize documentation for clarity/simplicity (hopefully).
0.100 2012-04-19T01:28:25Z
View
7 lib/AnyEvent/HTTP/Message.pm
@@ -40,6 +40,13 @@ sub new {
$self->{body} = delete $self->{content}
if exists $self->{content};
+ $self->{body} = ''
+ if !defined $self->{body};
+
+ $self->{headers} = $self->{headers}
+ ? $class->_normalize_headers($self->{headers})
+ : {};
+
bless $self, $class;
}
View
162 lib/AnyEvent/HTTP/Request.pm
@@ -9,16 +9,42 @@ use parent 'AnyEvent::HTTP::Message';
=class_method new
-See L</SYNOPSIS> for usage example.
+Accepts the same argument list as
+L<AnyEvent::HTTP/http_request>
+(see L</parse_args>):
+
+ AnyEvent::HTTP::Request->new(
+ $method => $uri,
+ body => $body,
+ headers => \%headers,
+ %params,
+ sub { ... }
+ );
+
+Alternatively accepts an instance of
+L<HTTP::Request>
+with an optional hashref of extra attributes
+(see L</from_http_message>):
+
+ AnyEvent::HTTP::Request->new(
+ HTTP::Request->new( $method, $uri, $headers, $body ),
+ {
+ cb => sub { ... },
+ params => \%params,
+ }
+ );
-Accepts a list of arguments
-(like those that would be passed
-to
-L<AnyEvent::HTTP/http_request>)
-which will be passed through L</parse_args>.
+Also accepts a single hashref of named attributes
+(see L</ATTRIBUTES>):
-Alternatively a single hashref can be passed
-with anything listed in L</ATTRIBUTES> as the keys.
+ AnyEvent::HTTP::Request->new({
+ method => 'POST',
+ uri => 'http://example.com',
+ cb => sub { ... },
+ params => \%params,
+ headers => \%headers,
+ body => $body,
+ });
=cut
@@ -28,17 +54,6 @@ sub new {
$self->{method} = uc $self->{method};
- # allow these to be constructor arguments
- # but store them in params to keep things simple
- foreach my $key ( qw( body headers ) ){
- $self->{params}->{$key} = delete $self->{$key}
- if exists $self->{$key};
- }
-
- if( my $h = $self->{params}->{headers} ){
- $self->{params}->{headers} = $self->_normalize_headers($h);
- }
-
return $self;
}
@@ -51,7 +66,11 @@ L<AnyEvent::HTTP/http_request>
and return a hashref which will be the basis for the object.
The list should look like
-C<< ($method, $uri, %params, \&callback) >>.
+C<< ($method, $uri, %optional, \&callback) >>
+where the C<%optional> hash may include C<body>, C<headers>,
+and any of the other options accepted by
+L<AnyEvent::HTTP/http_request>
+(which will become L</params>).
=cut
@@ -70,6 +89,35 @@ sub parse_args {
cb => pop,
params => { @_ },
};
+
+ # remove these from params
+ $args->{$_} = delete $args->{params}{$_}
+ for qw( body headers );
+
+ return $args;
+}
+
+=class_method from_http_message
+
+Called by the constructor
+when L</new> is passed an instance of L<HTTP::Request>.
+
+Since only L</method>, L</uri>, L</headers>, and L</body>
+can be determined from L<HTTP::Request>,
+a hashref can be passed as a second parameter
+containing L</cb> and L</params>.
+
+=cut
+
+sub from_http_message {
+ my ($self, $req, $extra) = @_;
+ my $args = {
+ method => $req->method,
+ uri => $req->uri,
+ headers => $self->_hash_http_headers($req->headers),
+ body => $req->content,
+ (ref($extra) eq 'HASH' ? %$extra : ()),
+ };
return $args;
}
@@ -85,6 +133,8 @@ sub args {
my ($self) = @_;
return (
$self->method => $self->uri,
+ body => $self->body,
+ headers => $self->headers,
%{ $self->params },
$self->cb,
);
@@ -116,6 +166,9 @@ B<Note> that these are connection params like
C<persistent> and C<timeout>,
not query params like in C<CGI>.
+B<Note> that C<body> and C<headers> will not be included,
+these are essentially I<user-agent> parameters.
+
=cut
sub method { $_[0]->{method} }
@@ -126,22 +179,15 @@ sub params { $_[0]->{params} ||= {} }
=attr headers
A hashref of the HTTP request headers
-(the C<headers> key of L</params>)
=attr body
-Request content body (if any)
-(the C<body> key of L</params>)
+Request content body
=attr content
Alias for L</body>
-=cut
-
-sub headers { $_[0]->params->{headers} ||= {} }
-sub body { $_[0]->params->{body} }
-
=method send
Actually submit the request by passing L</args>
@@ -156,25 +202,52 @@ sub send {
&AnyEvent::HTTP::http_request( $self->args );
}
+=method to_http_message
+
+Returns an instance of L<HTTP::Request>
+to provide additional functionality.
+
+B<Note> that L</cb> and L</params>
+will not be represented in the L<HTTP::Request> object
+(since they are for the user-agent and not the request).
+
+=cut
+
+sub to_http_message {
+ my ($self) = @_;
+ require HTTP::Request;
+
+ my $res = HTTP::Request->new(
+ $self->method,
+ $self->uri,
+ [ %{ $self->headers } ],
+ $self->body
+ );
+ return $res;
+}
+
1;
=for test_synopsis
-my ($body, %params, %headers, $uri);
+my ($uri, $body, %headers, %params);
=head1 SYNOPSIS
- # parse argument list for AnyEvent::HTTP::http_request
- AnyEvent::HTTP::Request->new(GET => $uri, %params, sub { ... });
-
- # or use a hashref of named arguments
- AnyEvent::HTTP::Request->new({
- method => 'POST',
- uri => 'http://example.com',
- cb => sub { ... },
- params => \%params,
+ # parses the same argument list as AnyEvent::HTTP::http_request:
+ my $req = AnyEvent::HTTP::Request->new(
+ POST => $uri,
+ body => $body,
headers => \%headers,
- body => $body,
- });
+ %params,
+ sub { .. }
+ );
+
+ # provides introspection
+ $req->header('user-agent');
+ printf STDERR "URI: %s\n", $req->uri;
+
+ # can be upgraded to an HTTP::Request object:
+ my $http_req = $req->to_http_message;
=head1 DESCRIPTION
@@ -209,14 +282,15 @@ You can then call L</send> to actually make the request
(via L<AnyEvent::HTTP/http_request>),
or L</args> to get the list of arguments the object would pass.
-=head1 TODO
-
-=for :list
-* Provide conversion to/from more featureful L<HTTP::Request>
+It can also be converted L<from|/from_http_message> or L<to|/to_http_message>
+the more featureful
+L<HTTP::Request>.
=head1 SEE ALSO
=for :list
+* L<AnyEvent::HTTP>
* L<AnyEvent::HTTP::Message> (base class)
+* L<HTTP::Request> - More featureful object
=cut
View
85 lib/AnyEvent/HTTP/Response.pm
@@ -9,29 +9,28 @@ use parent 'AnyEvent::HTTP::Message';
=class_method new
-See L</SYNOPSIS> for usage example.
-
-Accepts a list of arguments
-(like those that would be passed
-to the callback in
-L<AnyEvent::HTTP/http_request>)
-which will be passed through L</parse_args>.
+Accepts an argument list like the callback provided to
+L<AnyEvent::HTTP/http_request>
+(see L</parse_args>):
-Alternatively a single hashref can be passed
-with anything listed in L</ATTRIBUTES> as the keys.
+ AnyEvent::HTTP::Response->new($body, \%headers);
-=cut
+Alternatively accepts an instance of
+L<HTTP::Response>
+(see L</from_http_message>):
-sub new {
- my $class = shift;
- my $self = $class->SUPER::new(@_);
+ AnyEvent::HTTP::Response->new(
+ HTTP::Response->new( $code, $reason, $headers, $body )
+ );
- if( my $h = $self->{headers} ){
- $self->{headers} = $self->_normalize_headers($h);
- }
+Also accepts a single hashref of named attributes
+(see L</ATTRIBUTES>):
- return $self;
-}
+ AnyEvent::HTTP::Response->new({
+ body => $body,
+ headers => \%headers,
+ pseudo_headers => \%pseudo,
+ });
=method args
@@ -166,32 +165,25 @@ sub to_http_message {
1;
=for test_synopsis
-my ($body, %headers, %pseudo);
+my ($uri);
=head1 SYNOPSIS
- # argument list like the callback for AnyEvent::HTTP::http_request
- AnyEvent::HTTP::Response->new($body, \%headers);
-
- # named arguments (via hashref):
- AnyEvent::HTTP::Response->new({
- body => $body,
- headers => \%headers,
- pseudo_headers => \%pseudo,
- });
-
- # from LWP's HTTP::Response
- use HTTP::Response;
- AnyEvent::HTTP::Response->new(
- HTTP::Response->new( $code, $reason, [header => 'value', ], $body )
- );
-
- # psgi
- use HTTP::Message::PSGI;
- AnyEvent::HTTP::Response->new(
- HTTP::Response->from_psgi(
- [$code, [header => 'value', ], [$body]]
- )
+ AnyEvent::HTTP::http_request(
+ GET => $uri,
+ sub {
+ my $res = AnyEvent::HTTP::Response->new(@_);
+
+ # inspect attributes
+ print $res->header('Content-Type');
+ print $res->body;
+
+ # upgrade to HTTP::Response
+ my $http_res = $res->to_http_message;
+ if( !$http_res->is_success ){
+ print $http_res->status_line;
+ }
+ }
);
=head1 DESCRIPTION
@@ -200,9 +192,20 @@ This object represents an HTTP response from L<AnyEvent::HTTP>.
This is a companion class to L<AnyEvent::HTTP::Request>.
+It parses the arguments passed to the final callback in
+L<AnyEvent::HTTP/http_request>
+(or produces the arguments that should be passed to that,
+depending on how you'd like to use it).
+and wraps them in an object.
+
+It can also be converted L<from|/from_http_message> or L<to|/to_http_message>
+the more featureful
+L<HTTP::Response>.
+
=head1 SEE ALSO
=for :list
+* L<AnyEvent::HTTP>
* L<AnyEvent::HTTP::Message> (base class)
* L<HTTP::Response> More featureful object
* L<HTTP::Message::PSGI> Create an L<HTTP::Response> from a L<PSGI> arrayref
View
81 t/request.t
@@ -1,6 +1,8 @@
use strict;
use warnings;
use Test::More 0.88;
+use lib 't/lib';
+use AEHTTP_Tests;
my $mod = 'AnyEvent::HTTP::Request';
eval "require $mod" or die $@;
@@ -24,6 +26,7 @@ foreach my $args ( [], [1,2], [1,2,3,4] ){
my $req = new_ok($mod, [
post => 'scheme://host/path',
persistent => 1,
+ timeout => 3,
body => 'rub a dub',
headers => {
User_Agent => 'Any-Thing/0.1',
@@ -47,8 +50,7 @@ foreach my $args ( [], [1,2], [1,2,3,4] ){
my $exp_params = {
persistent => 1,
- headers => $exp_headers,
- body => 'rub a dub',
+ timeout => 3,
};
is_deeply $req->params, $exp_params, 'params include headers';
@@ -57,14 +59,29 @@ foreach my $args ( [], [1,2], [1,2,3,4] ){
my @args = $req->args;
is_deeply
- [ @args[0,1,8] ],
+ [ @args[0, 1, 10] ],
[ POST => 'scheme://host/path', $cb ],
'outer args correct';
- is_deeply { @args[2 .. 7] }, $exp_params, 'params in the middle of args';
+ is_deeply
+ { @args[2 .. 9] },
+ {
+ headers => $exp_headers,
+ body => 'rub a dub',
+ %$exp_params,
+ },
+ 'params in the middle of args';
is $req->cb->(), 'ugly', 'ugly duckling';
test_send($req);
+
+ test_http_message $req, sub {
+ my $msg = shift;
+ is $msg->method, 'POST', 'method';
+ is $msg->uri, 'scheme://host/path', 'uri';
+ is $msg->header('user_agent'), 'Any-Thing/0.1', 'ua header';
+ is $msg->content, 'rub a dub', 'body/content';
+ };
}
# empty params
@@ -76,24 +93,26 @@ foreach my $args ( [], [1,2], [1,2,3,4] ){
is $req->uri, '//bar/baz', 'request uri';
is $req->cb, $cb, 'callback';
- is $req->body, undef, 'no content';
- is $req->content, undef, 'content alias';
+ is $req->body, '', 'no content';
+ is $req->content, '', 'content alias';
is_deeply $req->params, {}, 'empty params';
is_deeply $req->headers, {}, 'empty headers';
$req->headers->{qux} = 42;
- is_deeply
- $req->params,
- {
- headers => {
- qux => 42,
- },
- },
- 'params contains headers';
+ is_deeply $req->params, {}, 'params still empty (headers not included)';
+ is_deeply $req->headers, {qux => 42}, 'headers no longer empty';
is $req->cb->(), 'fbbq', 'callback works';
test_send($req);
+
+ test_http_message $req, sub {
+ my $msg = shift;
+ is $msg->method, 'FOO', 'method';
+ is $msg->uri, '//bar/baz', 'uri';
+ is $msg->header('QUX'), '42', 'single header';
+ is $msg->content, '', 'body/content (empty string)';
+ };
}
# construct via hashref
@@ -141,8 +160,42 @@ foreach my $args ( [], [1,2], [1,2,3,4] ){
is $args[-1]->(), 'yee haw', 'correct callback results';
test_send($req);
+
+ test_http_message $req, sub {
+ my $msg = shift;
+ is $msg->method, 'YAWN', 'method';
+ is $msg->uri, 'horse://sense', 'uri';
+ is $msg->header('Wa'), 'hoo', 'single header';
+ is $msg->header('X-Wa'), 'x-hoo', 'single header';
+ is $msg->content, 'by cowboy', 'body/content';
+ };
}
+test_http_message sub {
+ my $msg = new_ok('HTTP::Request', [
+ GET => 'blue://buildings',
+ [
+ x_rain => 'king',
+ user_agent => 'perfect',
+ User_Agent => 'round here',
+ ],
+ 'anna begins',
+ ]);
+
+ my $suffix = 'from HTTP::Request';
+ my $req = new_ok($mod, [$msg]);
+ is $req->method, 'GET', "method $suffix";
+ is $req->uri, 'blue://buildings', "uri $suffix";
+ is $req->body, 'anna begins', "body $suffix";
+ is_deeply
+ $req->headers,
+ {
+ 'x-rain' => 'king',
+ 'user-agent' => 'perfect,round here',
+ },
+ "converted headers $suffix";
+};
+
done_testing;
# AE http_request overridden above

No commit comments for this range

Something went wrong with that request. Please try again.