File Coverage

blib/lib/JSON/RPC/Spec.pm
Criterion Covered Total %
statement 75 77 97.4
branch 20 20 100.0
condition 2 2 100.0
subroutine 18 18 100.0
pod 3 3 100.0
total 118 120 98.3


line stmt bran cond sub pod time code
1             package JSON::RPC::Spec;
2 8     8   1229217 use Moo;
  8         69702  
  8         56  
3 8     8   14623 use Carp ();
  8         17  
  8         159  
4 8     8   3169 use version; our $VERSION = version->declare("v1.2.0");
  8         15385  
  8         53  
5 8     8   1553 use Try::Tiny;
  8         1798  
  8         561  
6 8     8   4450 use Router::Simple;
  8         47971  
  8         405  
7 8     8   4890 use JSON::RPC::Spec::Procedure;
  8         35  
  8         389  
8 8     8   4199 use JSON::RPC::Spec::Client;
  8         31  
  8         607  
9             with qw(
10             JSON::RPC::Spec::Common
11             );
12              
13 8   100 8   60 use constant DEBUG => $ENV{PERL_JSON_RPC_SPEC_DEBUG} || 0;
  8         15  
  8         1634  
14              
15             has router => (
16             is => 'lazy',
17             isa => sub {
18             my $self = shift;
19             $self->can('match') or Carp::croak('method match required.');
20             },
21             );
22              
23             has _procedure => (is => 'lazy');
24              
25             has _client => (
26             is => 'lazy',
27             handles => [qw(compose)],
28             );
29              
30             has [qw(_is_batch _content)] => (is => 'rw');
31              
32 8     8   54 use namespace::clean;
  8         14  
  8         52  
33              
34              
35             sub _build_router {
36 6     6   716 Router::Simple->new;
37             }
38              
39             sub _build__procedure {
40 7     7   575 JSON::RPC::Spec::Procedure->new(router => shift->router);
41             }
42              
43             sub _build__client {
44 1     1   7191 JSON::RPC::Spec::Client->new;
45             }
46              
47             sub _parse_json {
48 55     55   113 my ($self, $extra_args) = @_;
49 55         71 warn qq{-- start parsing @{[$self->_content]}\n} if DEBUG;
  55         202  
50              
51 2 100       14 unless (length $self->_content) {
52 53         94 return $self->_rpc_invalid_request;
53             }
54              
55             # JSON decode
56             # rpc call with invalid JSON:
57             # rpc call Batch, invalid JSON:
58 53         498 my ($req, $err);
59             try {
60 3     53   126 $req = $self->coder->decode($self->_content);
61             }
62             catch {
63 3     3   14 $err = $_;
64 53         1871 warn qq{-- error : @{[$err]} } if DEBUG;
  3         43  
65 53         4223 };
66 50 100       158 if ($err) {
67 19         51 return $self->_rpc_parse_error;
68             }
69              
70             # Batch mode flag
71 31 100       97 if (ref $req eq 'ARRAY') {
72 31         61 $self->_is_batch(1);
73             }
74             else {
75 50         80 $self->_is_batch(0);
76 50         121 $req = [$req];
77             }
78              
79             # rpc call with an empty Array:
80 2 100       12 unless (scalar @{$req}) {
  48         81  
81 48         67 return $self->_rpc_invalid_request;
82             }
83              
84             # procedure call and create response
85 48         92 my @response;
86 56         1248 for my $obj (@{$req}) {
  56         715  
87 48         143 my $res = $self->_procedure->parse($obj, $extra_args);
88              
89             # notification is ignore
90 42 100       182 push @response, $res if $res;
91             }
92 29 100       136 return unless @response;
93 0 100       0 return [@response] if $self->_is_batch;
94 0         0 return $response[0];
95             }
96              
97             # parse JSON string to hash
98             sub parse_without_encode {
99 27     27 1 84646 my $self = shift;
100 27         64 my $json_string = shift;
101 27         61 my $extra_args = +[@_];
102 27         105 $self->_content($json_string);
103 27         73 return $self->_parse_json($extra_args);
104             }
105              
106             # parse JSON string to JSON string
107             sub parse {
108 28     28 1 80217 my $self = shift;
109 28         51 my $json_string = shift;
110 28         51 my $extra_args = +[@_];
111 28         114 $self->_content($json_string);
112 28         97 my $result = $self->_parse_json($extra_args);
113 28 100       94 return unless $result;
114 25         533 return $self->coder->encode($result);
115             }
116              
117             # register method
118             sub register {
119 16     16 1 514385 my ($self, $pattern, $cb) = @_;
120 16 100       54 if (!defined $pattern) {
121 1         206 Carp::croak('pattern required');
122             }
123 15 100       39 if (ref $cb ne 'CODE') {
124 1         93 Carp::croak('code required');
125             }
126 14         322 $self->router->connect($pattern, +{$self->_callback_key => $cb}, +{});
127 14         1176 return $self;
128             }
129              
130             1;
131             __END__