1package JSON::RPC::Parser; 2use strict; 3use JSON::RPC::Procedure; 4use Carp (); 5use Plack::Request; 6use Class::Accessor::Lite 7 new => 1, 8 rw => [ qw( 9 coder 10 ) ] 11; 12 13sub construct_procedure { 14 my $self = shift; 15 JSON::RPC::Procedure->new( @_ ); 16} 17 18sub construct_from_req { 19 my ($self, $req) = @_; 20 21 my $method = $req->method; 22 my $proc; 23 if ($method eq 'POST') { 24 $proc = $self->construct_from_post_req( $req ); 25 } elsif ($method eq 'GET') { 26 $proc = $self->construct_from_get_req( $req ); 27 } else { 28 Carp::croak( "Invalid method: $method" ); 29 } 30 31 return $proc; 32} 33 34sub construct_from_post_req { 35 my ($self, $req) = @_; 36 37 my $request = eval { $self->coder->decode( $req->content ) }; 38 if ($@) { 39 Carp::croak( "JSON parse error: $@" ); 40 } 41 42 my $ref = ref $request; 43 if ($ref ne 'ARRAY') { 44 $request = [ $request ]; 45 } 46 47 my @procs; 48 foreach my $req ( @$request ) { 49 Carp::croak( "Invalid parameter") unless ref $req eq 'HASH'; 50 push @procs, $self->construct_procedure( 51 method => $req->{method}, 52 id => $req->{id}, 53 params => $req->{params}, 54 ); 55 } 56 return \@procs; 57} 58 59sub construct_from_get_req { 60 my ($self, $req) = @_; 61 62 my $params = $req->query_parameters; 63 my $decoded_params; 64 if ($params->{params}) { 65 $decoded_params = eval { $self->coder->decode( $params->{params} ) }; 66 } 67 return [ 68 $self->construct_procedure( 69 method => $params->{method}, 70 id => $params->{id}, 71 params => $decoded_params 72 ) 73 ]; 74} 75 761; 77 78__END__ 79 80=head1 NAME 81 82JSON::RPC::Parser - Parse JSON RPC Requests from Plack::Request 83 84=head1 SYNOPSIS 85 86 use JSON::RPC::Parser; 87 88 my $parser = JSON::RPC::Parser->new( 89 coder => JSON->new 90 ); 91 my $procedure = $parser->construct_from_req( $request ); 92 93=head1 DESCRIPTION 94 95Constructs a L<JSON::RPC::Procedure> object from a Plack::Request object 96 97=cut 98