Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
path_info support
  • Loading branch information
nothingmuch committed Jul 14, 2008
1 parent 45513b5 commit 2b6cee3
Show file tree
Hide file tree
Showing 2 changed files with 115 additions and 16 deletions.
60 changes: 44 additions & 16 deletions lib/JSON/RPC/Common/Marshal/HTTP.pm
Expand Up @@ -133,9 +133,9 @@ sub call_to_request {
}

sub call_to_post_request {
my ( $self, $call, %args ) = @_;
my ( $self, $call, @args ) = @_;

my $uri = $args{uri} || URI->new("/");
my $uri = $self->call_reconstruct_uri_base($call, @args);

my $encoded = $self->call_to_json($call);

Expand Down Expand Up @@ -177,10 +177,30 @@ sub call_to_uri {
}
}

sub call_to_encoded_uri {
sub call_reconstruct_uri_base {
my ( $self, $call, %args ) = @_;

my $uri = $args{uri} ? $args{uri}->clone : URI->new("/");
if ( my $base_path = $args{base_path} ) {
return URI->new($base_path);
} elsif ( my $uri = $args{uri} ) {
$uri = $uri->clone;

if ( my $path_info = $args{path_info} ) {
my $path = $uri->path;
$path =~ s/\Q$path_info\E$//;
$uri->path($path);
}

return $uri;
} else {
URI->new('/');
}
}

sub call_to_encoded_uri {
my ( $self, $call, @args ) = @_;

my $uri = $self->call_reconstruct_uri_base($call, @args);

my $deflated = $self->deflate_call($call);

Expand All @@ -198,7 +218,7 @@ sub call_to_encoded_uri {
sub call_to_query_uri {
my ( $self, $call, %args ) = @_;

my $uri = $args{uri} ? $args{uri}->clone : URI->new("/");
my $uri = $self->call_reconstruct_uri_base($call, %args);

my $deflated = $self->deflate_call( $call );

Expand Down Expand Up @@ -234,20 +254,20 @@ sub request_to_call {
sub get_request_to_call {
my ( $self, $request, @args ) = @_;

my $uri = $request->uri;

$self->uri_to_call($request->uri, request => $request, @args);
$self->uri_to_call(request => $request, @args);
}

sub uri_to_call {
my ( $self, $uri, @args ) = @_;
my ( $self, %args ) = @_;

my $uri = $args{uri} || ($args{request} || croak "Either 'uri' or 'request' is mandatory")->uri;

my $params = $uri->query_form_hash;

if ( exists $params->{params} and $self->prefer_encoded_get ) {
return $self->encoded_uri_to_call( $uri, @args );
return $self->encoded_uri_to_call( $uri, %args );
} else {
return $self->query_uri_to_call( $uri, @args );
return $self->query_uri_to_call( $uri, %args );
}
}

Expand Down Expand Up @@ -287,7 +307,7 @@ sub encoded_uri_to_call {

# the less sane but occasionally useful way, 1.1-wd
sub query_uri_to_call {
my ( $self, $uri, @args ) = @_;
my ( $self, $uri, %args ) = @_;

my $params = $uri->query_form_hash;

Expand All @@ -299,15 +319,23 @@ sub query_uri_to_call {
}
}

if ( !exists($rpc{method}) and $self->rest_style_methods ) {
my ( $method ) = ( $uri->path =~ m{/(\w+)$} );
$rpc{method} = $method;
if ( !exists($rpc{method}) and $args{rest_style_methods} || $self->rest_style_methods ) {
if ( my $path_info = $args{path_info} ) {
( $rpc{method} = $path_info ) =~ s{^/}{};
} elsif ( my $base = $args{base_path} ) {
my ( $method ) = ( $uri->path =~ m{^\Q$base\E(.*)$} );
$method =~ s{^/}{};
$rpc{method} = $method;
} else {
my ( $method ) = ( $uri->path =~ m{/(\w+)$} );
$rpc{method} = $method;
}
}

$rpc{version} ||= "1.1";

# increases usefulness
$rpc{params} = $self->expand_query_params($params, @args);
$rpc{params} = $self->expand_query_params($params, %args);

$self->inflate_call(\%rpc);
}
Expand Down
71 changes: 71 additions & 0 deletions t/marshal_http.t
Expand Up @@ -68,6 +68,77 @@ use ok 'JSON::RPC::Common::Marshal::HTTP';
}
}

{
my $m_http = JSON::RPC::Common::Marshal::HTTP->new;


my %reqs = (
"explicit path_info & base" => [
HTTP::Request->new( GET => '/some/app/rpc/elaborate/method?version=1.1&id=4&oink=3&oink=2&bar=elk' ),
path_info => "/elaborate/method",
base_path => "/some/app/rpc",
],
"just base" => [
HTTP::Request->new( GET => '/some/app/rpc/elaborate/method?version=1.1&id=4&oink=3&oink=2&bar=elk' ),
base_path => "/some/app/rpc",
],
);

foreach my $req ( keys %reqs ) {
my ( $req_obj, %args ) = @{$reqs{$req}};

ok( my $call = $m_http->request_to_call($req_obj, %args), "$req into proc call" );

isa_ok( $call, "JSON::RPC::Common::Procedure::Call" );

is( $call->version, "1.1", "version" );
is( $call->method, "elaborate/method", "method" );
is( $call->id, 4, "id" );
is_deeply( $call->params, { oink => [ 3, 2 ], bar => "elk" }, "params" );

foreach my $opts (
{},
{ prefer_get => 0 },
{ prefer_get => 1, encoded => 0, rest_style_methods => 1 },
{ prefer_get => 1, encoded => 0, rest_style_methods => 0, },
{ prefer_get => 1, encoded => 1, }, # rest style methods don't apply
) {
ok( my $re_req = $m_http->call_to_request($call, %args, %$opts), "$req back through call_to_request (" . ( $opts->{prefer_get} ? ( $opts->{encode} ? "en" : "de" ) . "coded get" : "post" ) . ")" );
isa_ok( $re_req, "HTTP::Request" );

if ( $opts->{rest_style_methods} ) {
like( $re_req->uri->path, qr{rpc/elaborate/method$}, "method is in PATH_INFO" );
} else {
unlike( $re_req->uri->path, qr{elaborate}, "method is not in path at all" );

if ( $opts->{prefer_get} ) {
is( $re_req->uri->query_param("method"), "elaborate/method", "method is a param" );
}
}

like( $re_req->uri, qr{^/some/app/rpc}, "base path" );

ok( my $re_call = $m_http->request_to_call( $re_req, %args ), "round tripped call" );

my $def_1 = $call->deflate;
my $def_2 = $re_call->deflate;

if ( $opts->{prefer_get} ) {
# GET can't guarantee version, we need to scrub that
foreach my $hash ( $def_1, $def_2 ) {
foreach my $key qw(version jsonrpc) {
delete $hash->{$key};
}
}
}

use Data::Dumper;
is_deeply( $def_1, $def_2, "round trip call is_deeply first one" )
or diag Dumper($def_1, $def_2, $re_req, $opts);
}
}
}

{
my $m_http = JSON::RPC::Common::Marshal::HTTP->new;

Expand Down

0 comments on commit 2b6cee3

Please sign in to comment.