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