The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
Build.PL 11
Changes 07
META.json 1517
META.yml 2214
lib/JSON/RPC/Dispatch.pm 29
lib/JSON/RPC/Legacy/Client.pm 11
lib/JSON/RPC/Legacy/Procedure.pm 11
lib/JSON/RPC/Legacy/Server/Apache2.pm 11
lib/JSON/RPC/Legacy/Server/CGI.pm 11
lib/JSON/RPC/Legacy/Server/Daemon.pm 11
lib/JSON/RPC/Legacy/Server.pm 11
lib/JSON/RPC/Parser.pm 1015
lib/JSON/RPC.pm 11
t/002_basic.t 029
t/003_parser.t 94
15 files changed (This is a version diff) 66103
@@ -34,7 +34,7 @@ my %args = (
     test_files           => ((-d '.git' || $ENV{RELEASE_TESTING}) && -d 'xt') ? 't/ xt/' : 't/',
     recursive_test_files => 1,
 
-    
+
 );
 if (-d 'share') {
     $args{share_dir} = 'share';
@@ -1,6 +1,13 @@
 Changes
 =======
 
+1.06 2014-10-07T01:58:56Z
+    - Messed up previous release. Re-releasing
+
+1.05 2014-10-07T01:57:38Z
+    - Work better with batch requests: Now responses are properly returned
+      as list as long as the request is a list as well (Arata Makoto)
+
 1.04 2014-05-29T11:42:19Z
     - Work with notifications, which are procedures without an id
       (Kirill Bogdanov)
@@ -4,7 +4,7 @@
       "Daisuke Maki"
    ],
    "dynamic_config" : 0,
-   "generated_by" : "Minilla/v0.12.0",
+   "generated_by" : "Minilla/v1.1.0",
    "license" : [
       "perl_5"
    ],
@@ -44,7 +44,8 @@
       "develop" : {
          "requires" : {
             "Test::CPAN::Meta" : "0",
-            "Test::MinimumVersion" : "0.10108",
+            "Test::MinimumVersion::Fast" : "0.04",
+            "Test::PAUSE::Permissions" : "0.04",
             "Test::Pod" : "1.41",
             "Test::Spellunker" : "v0.2.7"
          }
@@ -69,7 +70,7 @@
    "provides" : {
       "JSON::RPC" : {
          "file" : "lib/JSON/RPC.pm",
-         "version" : "1.04"
+         "version" : "1.06"
       },
       "JSON::RPC::Constants" : {
          "file" : "lib/JSON/RPC/Constants.pm"
@@ -82,11 +83,11 @@
       },
       "JSON::RPC::Legacy::Client" : {
          "file" : "lib/JSON/RPC/Legacy/Client.pm",
-         "version" : "1.04"
+         "version" : "1.06"
       },
       "JSON::RPC::Legacy::Procedure" : {
          "file" : "lib/JSON/RPC/Legacy/Procedure.pm",
-         "version" : "1.04"
+         "version" : "1.06"
       },
       "JSON::RPC::Legacy::ReturnObject" : {
          "file" : "lib/JSON/RPC/Legacy/Client.pm",
@@ -94,22 +95,22 @@
       },
       "JSON::RPC::Legacy::Server" : {
          "file" : "lib/JSON/RPC/Legacy/Server.pm",
-         "version" : "1.04"
+         "version" : "1.06"
       },
       "JSON::RPC::Legacy::Server::Apache" : {
          "file" : "lib/JSON/RPC/Legacy/Server/Apache2.pm",
-         "version" : "1.04"
+         "version" : "1.06"
       },
       "JSON::RPC::Legacy::Server::Apache2" : {
          "file" : "lib/JSON/RPC/Legacy/Server/Apache2.pm"
       },
       "JSON::RPC::Legacy::Server::CGI" : {
          "file" : "lib/JSON/RPC/Legacy/Server/CGI.pm",
-         "version" : "1.04"
+         "version" : "1.06"
       },
       "JSON::RPC::Legacy::Server::Daemon" : {
          "file" : "lib/JSON/RPC/Legacy/Server/Daemon.pm",
-         "version" : "1.04"
+         "version" : "1.06"
       },
       "JSON::RPC::Legacy::Server::system" : {
          "file" : "lib/JSON/RPC/Legacy/Server.pm"
@@ -130,15 +131,15 @@
    "release_status" : "stable",
    "resources" : {
       "bugtracker" : {
-         "web" : "https://github.com/lestrrat/JSON-RPC/issues"
+         "web" : "ssh://git@github.com/lestrrat/JSON-RPC/issues"
       },
-      "homepage" : "https://github.com/lestrrat/JSON-RPC",
+      "homepage" : "ssh://git@github.com/lestrrat/JSON-RPC",
       "repository" : {
-         "url" : "git://github.com/lestrrat/JSON-RPC.git",
-         "web" : "https://github.com/lestrrat/JSON-RPC"
+         "url" : "ssh://git@github.com/lestrrat/JSON-RPC.git",
+         "web" : "ssh://git@github.com/lestrrat/JSON-RPC"
       }
    },
-   "version" : "1.04",
+   "version" : "1.06",
    "x_contributors" : [
       "Yoshimitsu Torii <yoshimitsu.torii@gmail.com>",
       "Stanislav Lechev [AngelFire] <af@0xAF.org>",
@@ -146,6 +147,7 @@
       "David Steinbrunner <dsteinbrunner@pobox.com>",
       "ThePeePs <patrick@thepeeps.net>",
       "Kirill Bogdanov <Sco76@hackerdom.ru>",
-      "lestrrat <lestrrat+github@gmail.com>"
+      "ar_tama <makoto.arata@dena.com>",
+      "Daisuke Maki <lestrrat+github@gmail.com>"
    ]
 }
@@ -12,7 +12,7 @@ configure_requires:
   CPAN::Meta::Prereqs: '0'
   Module::Build: '0.38'
 dynamic_config: 0
-generated_by: 'Minilla/v0.12.0, CPAN::Meta::Converter version 2.120921'
+generated_by: 'Minilla/v1.1.0, CPAN::Meta::Converter version 2.141520'
 license: perl
 meta-spec:
   url: http://module-build.sourceforge.net/META-spec-v1.4.html
@@ -31,55 +31,46 @@ no_index:
 provides:
   JSON::RPC:
     file: lib/JSON/RPC.pm
-    version: '1.04'
+    version: '1.06'
   JSON::RPC::Constants:
     file: lib/JSON/RPC/Constants.pm
-    version: 0
   JSON::RPC::Dispatch:
     file: lib/JSON/RPC/Dispatch.pm
-    version: 0
   JSON::RPC::Legacy:
     file: lib/JSON/RPC/Legacy.pm
-    version: 0
   JSON::RPC::Legacy::Client:
     file: lib/JSON/RPC/Legacy/Client.pm
-    version: '1.04'
+    version: '1.06'
   JSON::RPC::Legacy::Procedure:
     file: lib/JSON/RPC/Legacy/Procedure.pm
-    version: '1.04'
+    version: '1.06'
   JSON::RPC::Legacy::ReturnObject:
     file: lib/JSON/RPC/Legacy/Client.pm
     version: '0'
   JSON::RPC::Legacy::Server:
     file: lib/JSON/RPC/Legacy/Server.pm
-    version: '1.04'
+    version: '1.06'
   JSON::RPC::Legacy::Server::Apache:
     file: lib/JSON/RPC/Legacy/Server/Apache2.pm
-    version: '1.04'
+    version: '1.06'
   JSON::RPC::Legacy::Server::Apache2:
     file: lib/JSON/RPC/Legacy/Server/Apache2.pm
-    version: 0
   JSON::RPC::Legacy::Server::CGI:
     file: lib/JSON/RPC/Legacy/Server/CGI.pm
-    version: '1.04'
+    version: '1.06'
   JSON::RPC::Legacy::Server::Daemon:
     file: lib/JSON/RPC/Legacy/Server/Daemon.pm
-    version: '1.04'
+    version: '1.06'
   JSON::RPC::Legacy::Server::system:
     file: lib/JSON/RPC/Legacy/Server.pm
-    version: 0
   JSON::RPC::Legacy::ServiceObject:
     file: lib/JSON/RPC/Legacy/Client.pm
-    version: 0
   JSON::RPC::Parser:
     file: lib/JSON/RPC/Parser.pm
-    version: 0
   JSON::RPC::Procedure:
     file: lib/JSON/RPC/Procedure.pm
-    version: 0
   JSON::RPC::Test:
     file: lib/JSON/RPC/Test.pm
-    version: 0
 recommends:
   JSON::XS: '0'
 requires:
@@ -93,10 +84,10 @@ requires:
   Router::Simple: '0'
   parent: '0'
 resources:
-  bugtracker: https://github.com/lestrrat/JSON-RPC/issues
-  homepage: https://github.com/lestrrat/JSON-RPC
-  repository: git://github.com/lestrrat/JSON-RPC.git
-version: '1.04'
+  bugtracker: ssh://git@github.com/lestrrat/JSON-RPC/issues
+  homepage: ssh://git@github.com/lestrrat/JSON-RPC
+  repository: ssh://git@github.com/lestrrat/JSON-RPC.git
+version: '1.06'
 x_contributors:
   - 'Yoshimitsu Torii <yoshimitsu.torii@gmail.com>'
   - 'Stanislav Lechev [AngelFire] <af@0xAF.org>'
@@ -104,4 +95,5 @@ x_contributors:
   - 'David Steinbrunner <dsteinbrunner@pobox.com>'
   - 'ThePeePs <patrick@thepeeps.net>'
   - 'Kirill Bogdanov <Sco76@hackerdom.ru>'
-  - 'lestrrat <lestrrat+github@gmail.com>'
+  - 'ar_tama <makoto.arata@dena.com>'
+  - 'Daisuke Maki <lestrrat+github@gmail.com>'
@@ -86,11 +86,18 @@ sub handle_psgi {
         $req = Plack::Request->new($req);
     }
 
+    my $is_batch = 0;
     my @response;
     my $procedures;
     try {
         $procedures = $self->parser->construct_from_req( $req );
-        if (@$procedures <= 0) {
+        if (ref $procedures eq 'ARRAY') {
+            $is_batch = 1;
+        } else {
+            $procedures = [$procedures];
+        }
+        if (@$procedures <= 0 || not defined $procedures->[0]) {
+            $is_batch = 0;
             push @response, {
                 error => {
                     code => RPC_INVALID_REQUEST,
@@ -225,7 +232,7 @@ sub handle_psgi {
         $res = $req->new_response(200);
         $res->content_type( 'application/json; charset=utf8' );
         $res->body(
-            $self->coder->encode( @$procedures > 1 ? \@response : $response[0] )
+            $self->coder->encode( ($is_batch) ? \@response : $response[0] )
         );
         return $res->finalize;
     } else { # no content
@@ -11,7 +11,7 @@ use Carp ();
 
 package JSON::RPC::Legacy::Client;
 
-$JSON::RPC::Legacy::Client::VERSION = '1.04';
+$JSON::RPC::Legacy::Client::VERSION = '1.06';
 
 use LWP::UserAgent;
 
@@ -4,7 +4,7 @@ package JSON::RPC::Legacy::Procedure;
 # http://json-rpc.org/wd/JSON-RPC-1-1-WD-20060807.html
 #
 
-$JSON::RPC::Legacy::Procedure::VERSION = '1.04';
+$JSON::RPC::Legacy::Procedure::VERSION = '1.06';
 
 use strict;
 use attributes;
@@ -14,7 +14,7 @@ use Apache2::RequestIO ();
 use Apache2::RequestUtil ();
 
 
-$JSON::RPC::Legacy::Server::Apache::VERSION = '1.04';
+$JSON::RPC::Legacy::Server::Apache::VERSION = '1.06';
 
 
 sub handler {
@@ -7,7 +7,7 @@ use JSON::RPC::Legacy::Server; # for old Perl 5.005
 
 use base qw(JSON::RPC::Legacy::Server);
 
-$JSON::RPC::Legacy::Server::CGI::VERSION = '1.04';
+$JSON::RPC::Legacy::Server::CGI::VERSION = '1.06';
 
 sub new {
     my $class = shift;
@@ -5,7 +5,7 @@ use strict;
 use JSON::RPC::Legacy::Server; # for old Perl 5.005
 use base qw(JSON::RPC::Legacy::Server);
 
-$JSON::RPC::Legacy::Server::Daemon::VERSION = '1.04';
+$JSON::RPC::Legacy::Server::Daemon::VERSION = '1.06';
 
 use Data::Dumper;
 
@@ -25,7 +25,7 @@ BEGIN {
 }
 
 
-$JSON::RPC::Legacy::Server::VERSION = '1.04';
+$JSON::RPC::Legacy::Server::VERSION = '1.06';
 
 
 BEGIN {
@@ -41,7 +41,14 @@ sub construct_from_post_req {
 
     my $ref = ref $request;
     if ($ref ne 'ARRAY') {
-        $request = [ $request ];
+        # is not a batch request
+        return $self->construct_procedure(
+            method  => $request->{method},
+            id      => $request->{id},
+            params  => $request->{params},
+            jsonrpc => $request->{jsonrpc},
+            has_id  => exists $request->{id},
+        );
     }
 
     my @procs;
@@ -66,15 +73,13 @@ sub construct_from_get_req {
     if ($params->{params}) {
         $decoded_params = eval { $self->coder->decode( $params->{params} ) };
     }
-    return [
-        $self->construct_procedure(
-            method  => $params->{method},
-            id      => $params->{id},
-            params  => $decoded_params,
-            jsonrpc => $params->{jsonrpc},
-            has_id  => exists $params->{id},
-        )
-    ];
+    return $self->construct_procedure(
+        method  => $params->{method},
+        id      => $params->{id},
+        params  => $decoded_params,
+        jsonrpc => $params->{jsonrpc},
+        has_id  => exists $params->{id},
+    );
 }
 
 1;
@@ -1,6 +1,6 @@
 package JSON::RPC;
 use strict;
-our $VERSION = '1.04';
+our $VERSION = '1.06';
 
 1;
 
@@ -209,12 +209,41 @@ subtest 'normal dispatch' => sub {
 
     };
 
+    my $request_post_batch = sub {
+        my $cb = shift;
+
+        my ($req, $res, $post_content, $json);
+
+        my $headers = HTTP::Headers->new( Content_Type => 'application/json',);
+        my $uri = URI->new( "http://localhost" );
+        $post_content = $coder->encode(
+            [
+                {
+                    jsonrpc => '2.0',
+                    id     => 1,
+                    method => 'sum',
+                    params => [(1..3)],
+                }
+            ],
+        );
+        $req = HTTP::Request->new( POST => $uri, $headers, $post_content );
+        $res = $cb->( $req );
+
+        if (! ok $res->is_success, "response is success") {
+            diag $res->as_string;
+        }
+
+        $json = $coder->decode( $res->decoded_content );
+        is ref $json, 'ARRAY', 'response is array-ref';
+    };
+
     # XXX I want to test both Plack::Request and raw env, but test_rpc
     # makes it kinda hard... oh well, it's not /that/ much of a problem
     test_rpc $dispatch, sub {
         my $cb = shift;
         subtest 'JSONRPC via GET' => sub { $request_get->($cb) };
         subtest 'JSONRPC via POST' => sub { $request_post->($cb) };
+        subtest 'JSONRPC via POST (Batch)' => sub { $request_post_batch->($cb) };
         subtest 'JSONRPC Error' => sub { 
             my ($post_content, $req, $res, $json);
             my $headers = HTTP::Headers->new( Content_Type => 'application/json',);
@@ -15,10 +15,7 @@ subtest 'basic' => sub {
         coder => JSON->new,
     );
 
-    my $procedures = $parser->construct_from_req( $req );
-    ok $procedures, "procedures is defined";
-    is @$procedures, 1, "should be 1 procedure";
-    my $procedure = $procedures->[0];
+    my $procedure = $parser->construct_from_req( $req );
     ok $procedure, "procedure is defined";
     isa_ok $procedure, "JSON::RPC::Procedure";
     is $procedure->id, 1, "id matches";
@@ -40,8 +37,7 @@ subtest 'basic' => sub {
         CONTENT_LENGTH => $cl,
         CONTENT_TYPE   => 'application/json'
     } );
-    $procedures = $parser->construct_from_req( $req );
-    $procedure = $procedures->[0];
+    $procedure = $parser->construct_from_req( $req );
     is $procedure->jsonrpc, "2.0", "jsonrpc matches";
     ok $procedure->has_id, "has id";
     close $input;
@@ -56,8 +52,7 @@ subtest 'basic' => sub {
         CONTENT_LENGTH => $cl,
         CONTENT_TYPE   => 'application/json'
     } );
-    $procedures = $parser->construct_from_req( $req );
-    $procedure = $procedures->[0];
+    $procedure = $parser->construct_from_req( $req );
     ok !$procedure->has_id, "does not have an id";
     close $input;
 
@@ -82,7 +77,7 @@ subtest 'basic' => sub {
         CONTENT_LENGTH => $cl,
         CONTENT_TYPE   => 'application/json'
     } );
-    $procedures = $parser->construct_from_req( $req );
+    my $procedures = $parser->construct_from_req( $req );
     ok $procedures, "procedures are defined";
     is @$procedures, 2, "should be 2 procedures";
     ok (($procedures->[0]->has_id && $procedures->[1]->has_id), "both procedures have ids");