JSON-RPC-Common-0.11/0000755002053500205350000000000012304200774014163 5ustar dmcbridedmcbrideJSON-RPC-Common-0.11/examples/0000755002053500205350000000000012304200774016001 5ustar dmcbridedmcbrideJSON-RPC-Common-0.11/examples/http_engine.pl0000644002053500205350000000173012304200774020643 0ustar dmcbridedmcbride#!/usr/bin/perl use strict; use warnings; use HTTPEx::Declare; use JSON::RPC::Common::Marshal::HTTP; interface Standalone => { port => 8000, fork => 1, keepalive => 1 }; my $marshal = JSON::RPC::Common::Marshal::HTTP->new; run { my $c = shift; # decode the request into an object # this takes the JSON from the body, deserializes, and constructs a call eval { my $json_rpc_req = $marshal->request_to_call($c->req); # fake some sort of return value without actually calling anything my $json_rpc_res = $json_rpc_req->return_result({ time => scalar localtime, echo => { params => [ $json_rpc_req->params_list ], method => $json_rpc_req->method, }, }); # to invoke the request as a method of some object: # my $json_rpc_res = $json_rpc_req->call( $some_object ); # and write the result back to the HTTP client $marshal->write_result_to_response($json_rpc_res, $c->res); }; if ($@) { $c->res->status(500); $c->res->body($@); } }; JSON-RPC-Common-0.11/weaver.ini0000644002053500205350000000055512304200774016162 0ustar dmcbridedmcbride[@CorePrep] [Name] [Version] [Region / prelude] [Generic / SYNOPSIS] [Generic / DESCRIPTION] [Generic / OVERVIEW] [Collect / ATTRIBUTES] command = attr [Collect / METHODS] command = method [Collect / FUNCTIONS] command = func [Leftovers] [Region / postlude] [Generic / BUGS] [Generic / SEEALSO] header = SEE ALSO [Generic / SUPPORT] [Authors] [Legal] JSON-RPC-Common-0.11/LICENSE0000644002053500205350000004371412304200774015201 0ustar dmcbridedmcbrideThis software is copyright (c) 2014 by Yuval Kogman and others. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. Terms of the Perl programming language system itself a) the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version, or b) the "Artistic License" --- The GNU General Public License, Version 1, February 1989 --- This software is Copyright (c) 2014 by Yuval Kogman and others. This is free software, licensed under: The GNU General Public License, Version 1, February 1989 GNU GENERAL PUBLIC LICENSE Version 1, February 1989 Copyright (C) 1989 Free Software Foundation, Inc. 51 Franklin St, Suite 500, Boston, MA 02110-1335 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The license agreements of most software companies try to keep users at the mercy of those companies. By contrast, our General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. The General Public License applies to the Free Software Foundation's software and to any other program whose authors commit to using it. You can use it for your programs, too. When we speak of free software, we are referring to freedom, not price. Specifically, the General Public License is designed to make sure that you have the freedom to give away or sell copies of free software, that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of a such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must tell them their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any work containing the Program or a portion of it, either verbatim or with modifications. Each licensee is addressed as "you". 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this General Public License and to the absence of any warranty; and give any other recipients of the Program a copy of this General Public License along with the Program. You may charge a fee for the physical act of transferring a copy. 2. You may modify your copy or copies of the Program or any portion of it, and copy and distribute such modifications under the terms of Paragraph 1 above, provided that you also do the following: a) cause the modified files to carry prominent notices stating that you changed the files and the date of any change; and b) cause the whole of any work that you distribute or publish, that in whole or in part contains the Program or any part thereof, either with or without modifications, to be licensed at no charge to all third parties under the terms of this General Public License (except that you may choose to grant warranty protection to some or all third parties, at your option). c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the simplest and most usual way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this General Public License. d) You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. Mere aggregation of another independent work with the Program (or its derivative) on a volume of a storage or distribution medium does not bring the other work under the scope of these terms. 3. You may copy and distribute the Program (or a portion or derivative of it, under Paragraph 2) in object code or executable form under the terms of Paragraphs 1 and 2 above provided that you also do one of the following: a) accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Paragraphs 1 and 2 above; or, b) accompany it with a written offer, valid for at least three years, to give any third party free (except for a nominal charge for the cost of distribution) a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Paragraphs 1 and 2 above; or, c) accompany it with the information you received as to where the corresponding source code may be obtained. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form alone.) Source code for a work means the preferred form of the work for making modifications to it. For an executable file, complete source code means all the source code for all modules it contains; but, as a special exception, it need not include source code for modules which are standard libraries that accompany the operating system on which the executable file runs, or for standard header files or definitions files that accompany that operating system. 4. You may not copy, modify, sublicense, distribute or transfer the Program except as expressly provided under this General Public License. Any attempt otherwise to copy, modify, sublicense, distribute or transfer the Program is void, and will automatically terminate your rights to use the Program under this License. However, parties who have received copies, or rights to use copies, from you under this General Public License will not have their licenses terminated so long as such parties remain in full compliance. 5. By copying, distributing or modifying the Program (or any work based on the Program) you indicate your acceptance of this license to do so, and all its terms and conditions. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. 7. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of the license which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the license, you may choose any version ever published by the Free Software Foundation. 8. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to humanity, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19xx name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (a program to direct compilers to make passes at assemblers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice That's all there is to it! --- The Artistic License 1.0 --- This software is Copyright (c) 2014 by Yuval Kogman and others. This is free software, licensed under: The Artistic License 1.0 The Artistic License Preamble The intent of this document is to state the conditions under which a Package may be copied, such that the Copyright Holder maintains some semblance of artistic control over the development of the package, while giving the users of the package the right to use and distribute the Package in a more-or-less customary fashion, plus the right to make reasonable modifications. Definitions: - "Package" refers to the collection of files distributed by the Copyright Holder, and derivatives of that collection of files created through textual modification. - "Standard Version" refers to such a Package if it has not been modified, or has been modified in accordance with the wishes of the Copyright Holder. - "Copyright Holder" is whoever is named in the copyright or copyrights for the package. - "You" is you, if you're thinking about copying or distributing this Package. - "Reasonable copying fee" is whatever you can justify on the basis of media cost, duplication charges, time of people involved, and so on. (You will not be required to justify it to the Copyright Holder, but only to the computing community at large as a market that must bear the fee.) - "Freely Available" means that no fee is charged for the item itself, though there may be fees involved in handling the item. It also means that recipients of the item may redistribute it under the same conditions they received it. 1. You may make and give away verbatim copies of the source form of the Standard Version of this Package without restriction, provided that you duplicate all of the original copyright notices and associated disclaimers. 2. You may apply bug fixes, portability fixes and other modifications derived from the Public Domain or from the Copyright Holder. A Package modified in such a way shall still be considered the Standard Version. 3. You may otherwise modify your copy of this Package in any way, provided that you insert a prominent notice in each changed file stating how and when you changed that file, and provided that you do at least ONE of the following: a) place your modifications in the Public Domain or otherwise make them Freely Available, such as by posting said modifications to Usenet or an equivalent medium, or placing the modifications on a major archive site such as ftp.uu.net, or by allowing the Copyright Holder to include your modifications in the Standard Version of the Package. b) use the modified Package only within your corporation or organization. c) rename any non-standard executables so the names do not conflict with standard executables, which must also be provided, and provide a separate manual page for each non-standard executable that clearly documents how it differs from the Standard Version. d) make other distribution arrangements with the Copyright Holder. 4. You may distribute the programs of this Package in object code or executable form, provided that you do at least ONE of the following: a) distribute a Standard Version of the executables and library files, together with instructions (in the manual page or equivalent) on where to get the Standard Version. b) accompany the distribution with the machine-readable source of the Package with your modifications. c) accompany any non-standard executables with their corresponding Standard Version executables, giving the non-standard executables non-standard names, and clearly documenting the differences in manual pages (or equivalent), together with instructions on where to get the Standard Version. d) make other distribution arrangements with the Copyright Holder. 5. You may charge a reasonable copying fee for any distribution of this Package. You may charge any fee you choose for support of this Package. You may not charge a fee for this Package itself. However, you may distribute this Package in aggregate with other (possibly commercial) programs as part of a larger (possibly commercial) software distribution provided that you do not advertise this Package as a product of your own. 6. The scripts and library files supplied as input to or produced as output from the programs of this Package do not automatically fall under the copyright of this Package, but belong to whomever generated them, and may be sold commercially, and may be aggregated with this Package. 7. C or perl subroutines supplied by you and linked into this Package shall not be considered part of this Package. 8. The name of the Copyright Holder may not be used to endorse or promote products derived from this software without specific prior written permission. 9. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. The End JSON-RPC-Common-0.11/dist.ini~0000644002053500205350000000105512304200774016026 0ustar dmcbridedmcbridename = JSON-RPC-Common author = Yuval Kogman license = Perl_5 copyright_holder = Yuval Kogman and others [@Git] tag_format = JSON-RPC-Common-%v [Git::NextVersion] version_regexp = ^JSON-RPC-Common-(.+)$ [@Basic] [PkgVersion] [PodWeaver] [PodSyntaxTests] [ModuleBuild] [DualBuilders] [MetaJSON] [NextRelease] format = %-7v %{yyy-MM-dd}d [AutoPrereqs] skip = CGI::Expand [Prereqs] JSON = 2.11 Moose = 0.48 namespace::clean = 0.20 [Prereqs / TestRequires] Test::Exception = 0 [GithubMeta] JSON-RPC-Common-0.11/t/0000755002053500205350000000000012304200774014426 5ustar dmcbridedmcbrideJSON-RPC-Common-0.11/t/release-pod-syntax.t0000644002053500205350000000057012304200774020341 0ustar dmcbridedmcbride#!perl BEGIN { unless ($ENV{RELEASE_TESTING}) { require Test::More; Test::More::plan(skip_all => 'these tests are for release candidate testing'); } } # This file was automatically generated by Dist::Zilla::Plugin::PodSyntaxTests. use Test::More; eval "use Test::Pod 1.41"; plan skip_all => "Test::Pod 1.41 required for testing POD" if $@; all_pod_files_ok(); JSON-RPC-Common-0.11/t/marshal_http.t0000644002053500205350000001660012304200774017304 0ustar dmcbridedmcbride#!/usr/bin/perl use strict; use warnings; use utf8; use Encode; use Test::More; BEGIN { plan skip_all => "HTTP::Request required for this test" unless eval { require HTTP::Request }; plan skip_all => "HTTP::Response required for this test" unless eval { require HTTP::Response }; plan 'no_plan'; } use MIME::Base64 qw(encode_base64); use JSON::RPC::Common::Marshal::HTTP; { my $m_http = JSON::RPC::Common::Marshal::HTTP->new; my %reqs = ( "get with params" => HTTP::Request->new( GET => '/rpc?version=1.1&method=foo&id=4&oink=3&oink=2&bar=elk' ), "REST style" => HTTP::Request->new( GET => '/rpc/foo?version=1.1&id=4&oink=3&oink=2&bar=elk' ), "b64 encoded get" => HTTP::Request->new( GET => '/rpc?version=1.1&method=foo&id=4¶ms=' . encode_base64('{"oink":[3,2],"bar":"elk"}') ), "encoded get" => HTTP::Request->new( GET => '/rpc?version=1.1&method=foo&id=4¶ms={"oink":[3,2],"bar":"elk"}' ), "post" => HTTP::Request->new( POST => '/rpc', undef, q|{"version":"1.1","method":"foo","id":4,"params":{"oink":[3,2],"bar":"elk"}}| ), ); foreach my $req ( keys %reqs ) { my $req_obj = $reqs{$req}; ok( my $call = $m_http->request_to_call($req_obj), "$req into proc call" );; isa_ok( $call, "JSON::RPC::Common::Procedure::Call" ); is( $call->version, "1.1", "version" ); is( $call->method, "foo", "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, }, { prefer_get => 1, encoded => 1, }, ) { ok( my $re_req = $m_http->call_to_request($call, %$opts), "call_to_request" ); isa_ok( $re_req, "HTTP::Request" ); ok( my $re_call = $m_http->request_to_call( $re_req ), "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; 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; my $http_res = HTTP::Response->new( 200, "YATTA", undef, Encode::encode( utf8 => '{"jsonrpc":"2.0","result":"שלום","id":3}' ) ); my $res_obj = $m_http->response_to_result($http_res); is( $res_obj->version, "2.0", "version 2.0"); ok( !$res_obj->has_error, "no error" ); is( $res_obj->result, "שלום", "result" ); ok( utf8::is_utf8($res_obj->result), "unicode decoded" ); is( $res_obj->id, 3, "id" ); isa_ok( my $re_http_res = $m_http->result_to_response($res_obj), "HTTP::Response" ); ok( !utf8::is_utf8($re_http_res->content), "body is not unicode (encoded)" ); is( $re_http_res->content_length, length($re_http_res->content), "content length" ); ok( my $re_res = $m_http->response_to_result($re_http_res), "round trip result" ); ok( utf8::is_utf8($re_res->result), "unicode decoded" ); is_deeply( $re_res->deflate, $res_obj->deflate, "round trip result eq deeply", ); } { my $m_http = JSON::RPC::Common::Marshal::HTTP->new; my $http_res = HTTP::Response->new( 500, "OH NOES", undef, '{"jsonrpc":"2.0","error":{"message":"bork","code":3,"data":"horses"},"id":5}' ); my $res_obj = $m_http->response_to_result($http_res); is( $res_obj->version, "2.0", "version 2.0"); ok( !$res_obj->has_result, "no result" ); is( $res_obj->id, 5, "id" ); ok( $res_obj->has_error, "has error" ); my $error = $res_obj->error; isa_ok( $error, "JSON::RPC::Common::Procedure::Return::Error" ); isa_ok( $error, "JSON::RPC::Common::Procedure::Return::Version_2_0::Error" ); is( $error->code, 3, "error code" ); is( $error->message, "bork", "error message" ); is_deeply( $error->data, "horses", "error data" ); isa_ok( my $re_http_res = $m_http->result_to_response($res_obj), "HTTP::Response" ); ok( my $re_res = $m_http->response_to_result($re_http_res), "round trip result" ); is_deeply( $re_res->deflate, $res_obj->deflate, "round trip result eq deeply", ); } { my $m_http = JSON::RPC::Common::Marshal::HTTP->new; my $http_res = HTTP::Response->new( 500, "OH NOES", undef, '{}' ); my $res_obj = $m_http->response_to_result($http_res); ok( !$res_obj->has_result, "no result" ); ok( !$res_obj->has_id, "no id" ); ok( $res_obj->has_error, "has error" ); my $error = $res_obj->error; isa_ok( $error, "JSON::RPC::Common::Procedure::Return::Error" ); is( $error->message, "OH NOES", "error message" ); is_deeply( $error->data, { response => $http_res }, "error data" ); } SKIP: { plan skip "CGI::Expand is required", 2 unless eval { require CGI::Expand }; my $m_http = JSON::RPC::Common::Marshal::HTTP->new( expand => 1 ); my $req = HTTP::Request->new( GET => '/rpc?version=1.1&method=foo&id=4&oink.1=3&oink.0=2&bar.foo=elk' ); my $call = $m_http->request_to_call( $req ); isa_ok( $call, "JSON::RPC::Common::Procedure::Call" ); # note "oink" params are reversed is_deeply( $call->params, { oink => [ 2, 3 ], bar => { foo => "elk" } }, "expanded params" ); } JSON-RPC-Common-0.11/t/request_1_0.t0000644002053500205350000000345512304200774016751 0ustar dmcbridedmcbride#!/usr/bin/perl use strict; use warnings; use Test::More 'no_plan'; use JSON::RPC::Common::Procedure::Call; { my $req_data = { method => "hello", id => "foo", params => [ 1 .. 3 ], }; my $req_obj = JSON::RPC::Common::Procedure::Call->inflate($req_data); isa_ok( $req_obj, "JSON::RPC::Common::Procedure::Call" ); isa_ok( $req_obj, "JSON::RPC::Common::Procedure::Call::Version_1_0" ); is_deeply( $req_obj->deflate, $req_data, "round trip through deflate" ); is( $req_obj->version, "1.0", "version" ); ok( $req_obj->has_id, "has_id" ); is( $req_obj->id, "foo", "id value" ); ok( !$req_obj->is_notification, "not a notification" ); ok( !$req_obj->is_service, "not a service req" ); is_deeply( $req_obj->params, [ 1 .. 3 ], "params" ); is_deeply( [ $req_obj->params_list ], [ 1 .. 3 ], "params_list" ); my $res = $req_obj->return_result("moose"); isa_ok( $res, "JSON::RPC::Common::Procedure::Return" ); isa_ok( $res, "JSON::RPC::Common::Procedure::Return::Version_1_0" ); is_deeply( $res->deflate, { result => "moose", error => undef, id => "foo" }, "deflated" ); my $res_passthrough = JSON::RPC::Common::Procedure::Return->inflate($res->deflate); isa_ok( $res_passthrough, "JSON::RPC::Common::Procedure::Return", "reinflate result" ); ok( !$res_passthrough->has_error, "no error" ); is( $res->id, "foo", "ID" ); is( $res->result, "moose", "result" ); } { my $req_data = { method => "hello", id => undef, params => [ 1 .. 3 ], }; my $req_obj = JSON::RPC::Common::Procedure::Call->inflate($req_data); isa_ok( $req_obj, "JSON::RPC::Common::Procedure::Call" ); isa_ok( $req_obj, "JSON::RPC::Common::Procedure::Call::Version_1_0" ); is( $req_obj->version, "1.0", "version" ); ok( $req_obj->has_id, "has_id" ); ok( $req_obj->is_notification, "not a notification" ); } JSON-RPC-Common-0.11/t/request_1_1.t0000644002053500205350000000455312304200774016752 0ustar dmcbridedmcbride#!/usr/bin/perl use strict; use warnings; use Test::More 'no_plan'; use JSON::RPC::Common::Procedure::Call; { my $req_data = { version => "1.1", method => "hello", id => "foo", params => { foo => "bar" }, }; my $req_obj = JSON::RPC::Common::Procedure::Call->inflate($req_data); isa_ok( $req_obj, "JSON::RPC::Common::Procedure::Call" ); isa_ok( $req_obj, "JSON::RPC::Common::Procedure::Call::Version_1_1" ); is_deeply( $req_obj->deflate, $req_data, "round trip through deflate" ); is( $req_obj->version, "1.1", "version" ); ok( $req_obj->has_id, "has_id" ); is( $req_obj->id, "foo", "id value" ); ok( !$req_obj->is_notification, "not a notification" ); ok( !$req_obj->is_service, "not a service req" ); my $res = $req_obj->return_result("moose"); isa_ok( $res, "JSON::RPC::Common::Procedure::Return" ); isa_ok( $res, "JSON::RPC::Common::Procedure::Return::Version_1_1" ); is_deeply( $res->deflate, { version => "1.1", result => "moose", id => "foo" }, "deflated" ); } { my $req_data = { version => "1.1", method => "hello", id => undef, params => { foo => "bar" }, }; my $req_obj = JSON::RPC::Common::Procedure::Call->inflate($req_data); isa_ok( $req_obj, "JSON::RPC::Common::Procedure::Call" ); isa_ok( $req_obj, "JSON::RPC::Common::Procedure::Call::Version_1_1" ); is( $req_obj->version, "1.1", "version" ); ok( $req_obj->has_id, "has_id" ); ok( !$req_obj->is_notification, "not a notification" ); } { my $req_data = { version => "1.1", method => "hello", params => { foo => "bar" }, }; my $req_obj = JSON::RPC::Common::Procedure::Call->inflate($req_data); isa_ok( $req_obj, "JSON::RPC::Common::Procedure::Call" ); isa_ok( $req_obj, "JSON::RPC::Common::Procedure::Call::Version_1_1" ); is( $req_obj->version, "1.1", "version" ); ok( !$req_obj->has_id, "not has_id" ); ok( !$req_obj->is_notification, "no id is still not a notification" ); } { my $req_data = { version => "1.1", method => "hello", kwparams => { foo => "bar" }, }; my $req_obj = JSON::RPC::Common::Procedure::Call->inflate($req_data); isa_ok( $req_obj, "JSON::RPC::Common::Procedure::Call" ); isa_ok( $req_obj, "JSON::RPC::Common::Procedure::Call::Version_1_1" ); is_deeply( $req_obj->deflate, $req_data, "round trip through deflate" ); is( $req_obj->version, "1.1", "version" ); ok( $req_obj->alt_spec, "alt 1.1 detected" ); } JSON-RPC-Common-0.11/t/marshal.t0000644002053500205350000000277412304200774016254 0ustar dmcbridedmcbride#!/usr/bin/perl use strict; use warnings; use Test::More 'no_plan'; use Test::Exception; use JSON; use JSON::RPC::Common::Marshal::Text; { my $m_json = JSON::RPC::Common::Marshal::Text->new; isa_ok( $m_json, "JSON::RPC::Common::Marshal::Text" ); my $call = $m_json->json_to_message(<version, "2.0", "version" ); is( $call->id, "dancing", "id" ); my $res = $call->return_result("bah"); my $text = $m_json->message_to_json($res); is_deeply( from_json($text), { jsonrpc => "2.0", id => "dancing", result => "bah", }, "result encoding", ); ok( $m_json->json_to_call('{"jsonrpc":"2.0","params":{"foo":3},"method":"hello"}'), "notification (2.0)" ); my $no_ver = $m_json->json_to_call('{"id":"moo","params":[],"method":"hello"}'); ok( $no_ver, "missing version parsed" ); is( $no_ver->version, "1.0", "version 1.0" ); my %required = ( method => '{"jsonrpc":"2.0","params":{},"id":3}', # missing method params => '{"method":"hello","id":3}', # missing params id => '{"params":[],"method":"hello"}', # missing id (version 1.0) ); foreach my $req ( keys %required ) { throws_ok { $m_json->json_to_call($required{$req}); } qr/\Q$req\E.*required/, "required param $req"; } dies_ok { $m_json->json_to_call("adtjhat3!!!!") } "JSON parse error"; } JSON-RPC-Common-0.11/t/object.t0000644002053500205350000000210012304200774016052 0ustar dmcbridedmcbride#!/usr/bin/perl use strict; use warnings; use Test::More 'no_plan'; use JSON::RPC::Common::Procedure::Call; { package Foo; use Moose; sub hello { my ( $self, %args ) = @_; return "hello " . $args{greet}; } } { my $call = JSON::RPC::Common::Procedure::Call->new( method => "hello", params => { greet => "world" }, ); isa_ok( $call, "JSON::RPC::Common::Procedure::Call" ); can_ok( $call, "call" ); my $res = $call->call( Foo->new ); isa_ok( $res, "JSON::RPC::Common::Procedure::Return" ); ok( $res->has_result, "has result" ); is( $res->result, "hello world", "result" ); ok( !$res->has_error, "no error" ); } { my $call = JSON::RPC::Common::Procedure::Call->new( method => "does_not_exist", params => { }, ); my $res = $call->call( Foo->new ); isa_ok( $res, "JSON::RPC::Common::Procedure::Return" ); ok( !$res->has_result, "no result" ); ok( $res->has_error, "has error" ); isa_ok( $res->error, "JSON::RPC::Common::Procedure::Return::Error" ); like( $res->error->message, qr/does_not_exist/, "error talks about non existent method" ); } JSON-RPC-Common-0.11/t/request_2_0.t0000644002053500205350000000543712304200774016754 0ustar dmcbridedmcbride#!/usr/bin/perl use strict; use warnings; use Test::More 'no_plan'; use JSON::RPC::Common::Procedure::Call; { my $req_data = { jsonrpc => "2.0", method => "hello", id => "foo", params => { foo => "bar" }, }; my $req_obj = JSON::RPC::Common::Procedure::Call->inflate($req_data); is_deeply( $req_obj->deflate, $req_data, "round trip through deflate" ); isa_ok( $req_obj, "JSON::RPC::Common::Procedure::Call" ); isa_ok( $req_obj, "JSON::RPC::Common::Procedure::Call::Version_2_0" ); is( $req_obj->version, "2.0", "version" ); ok( $req_obj->has_id, "has_id" ); is( $req_obj->id, "foo", "id value" ); ok( !$req_obj->is_notification, "not a notification" ); ok( !$req_obj->is_service, "not a service req" ); is_deeply( $req_obj->params, { foo => "bar" }, "params" ); is_deeply( [ $req_obj->params_list ], [ qw(foo bar) ], "params_list" ); my $res_hash = $req_obj->return_result({ foo => "bar" }); isa_ok( $res_hash, "JSON::RPC::Common::Procedure::Return" ); isa_ok( $res_hash, "JSON::RPC::Common::Procedure::Return::Version_2_0" ); is_deeply( $res_hash->deflate, { result => { foo => "bar" }, id => "foo", jsonrpc => "2.0" }, "hash result" ); is_deeply( $req_obj->return_result( 1 .. 3 )->deflate, { result => [ 1 .. 3 ], id => "foo", jsonrpc => "2.0" }, "list result" ); } { my $req_data = { jsonrpc => "2.0", method => "hello", id => undef, params => { foo => "bar" }, }; my $req_obj = JSON::RPC::Common::Procedure::Call->inflate($req_data); isa_ok( $req_obj, "JSON::RPC::Common::Procedure::Call" ); isa_ok( $req_obj, "JSON::RPC::Common::Procedure::Call::Version_2_0" ); is( $req_obj->version, "2.0", "version" ); ok( $req_obj->has_id, "has_id" ); ok( !$req_obj->is_notification, "not a notification" ); } { my $req_data = { jsonrpc => "2.0", method => "hello", params => { foo => "bar" }, }; my $req_obj = JSON::RPC::Common::Procedure::Call->inflate($req_data); isa_ok( $req_obj, "JSON::RPC::Common::Procedure::Call" ); isa_ok( $req_obj, "JSON::RPC::Common::Procedure::Call::Version_2_0" ); is( $req_obj->version, "2.0", "version" ); ok( !$req_obj->has_id, "not has_id" ); ok( $req_obj->is_notification, "no id means notification" ); } { my $req_data = { jsonrpc => "2.0", method => "hello", id => "foo", params => { foo => "bar" }, }; my $req_obj = JSON::RPC::Common::Message->inflate($req_data); isa_ok( $req_obj, "JSON::RPC::Common::Procedure::Call" ); isa_ok( $req_obj, "JSON::RPC::Common::Procedure::Call::Version_2_0" ); } { my $req_data = { jsonrpc => "2.0", id => "foo", result => { foo => "bar" }, }; my $req_obj = JSON::RPC::Common::Message->inflate($req_data); isa_ok( $req_obj, "JSON::RPC::Common::Procedure::Return" ); isa_ok( $req_obj, "JSON::RPC::Common::Procedure::Return::Version_2_0" ); } JSON-RPC-Common-0.11/MANIFEST0000644002053500205350000000207712304200774015322 0ustar dmcbridedmcbride# This file was automatically generated by Dist::Zilla::Plugin::Manifest v5.012. Build.PL Changes LICENSE MANIFEST META.json META.yml Makefile.PL README dist.ini dist.ini~ examples/http_engine.pl lib/JSON/RPC/Common.pm lib/JSON/RPC/Common/Marshal/HTTP.pm lib/JSON/RPC/Common/Marshal/Text.pm lib/JSON/RPC/Common/Message.pm lib/JSON/RPC/Common/Procedure/Call.pm lib/JSON/RPC/Common/Procedure/Call/Version_1_0.pm lib/JSON/RPC/Common/Procedure/Call/Version_1_1.pm lib/JSON/RPC/Common/Procedure/Call/Version_2_0.pm lib/JSON/RPC/Common/Procedure/Return.pm lib/JSON/RPC/Common/Procedure/Return/Error.pm lib/JSON/RPC/Common/Procedure/Return/Version_1_0.pm lib/JSON/RPC/Common/Procedure/Return/Version_1_0/Error.pm lib/JSON/RPC/Common/Procedure/Return/Version_1_1.pm lib/JSON/RPC/Common/Procedure/Return/Version_1_1/Error.pm lib/JSON/RPC/Common/Procedure/Return/Version_2_0.pm lib/JSON/RPC/Common/Procedure/Return/Version_2_0/Error.pm lib/JSON/RPC/Common/TypeConstraints.pm t/marshal.t t/marshal_http.t t/object.t t/release-pod-syntax.t t/request_1_0.t t/request_1_1.t t/request_2_0.t weaver.ini JSON-RPC-Common-0.11/lib/0000755002053500205350000000000012304200774014731 5ustar dmcbridedmcbrideJSON-RPC-Common-0.11/lib/JSON/0000755002053500205350000000000012304200774015502 5ustar dmcbridedmcbrideJSON-RPC-Common-0.11/lib/JSON/RPC/0000755002053500205350000000000012304200774016126 5ustar dmcbridedmcbrideJSON-RPC-Common-0.11/lib/JSON/RPC/Common/0000755002053500205350000000000012304200774017356 5ustar dmcbridedmcbrideJSON-RPC-Common-0.11/lib/JSON/RPC/Common/Message.pm0000644002053500205350000000354012304200774021302 0ustar dmcbridedmcbride#!/usr/bin/perl package JSON::RPC::Common::Message; $JSON::RPC::Common::Message::VERSION = '0.11'; use Moose::Role; # ABSTRACT: JSON-RPC message role use Carp qw(croak); use Class::Load qw(); use namespace::clean -except => [qw(meta)]; requires 'deflate'; sub inflate { my ( $class, @args ) = @_; my $data; if (@args == 1) { if (defined $args[0]) { no warnings 'uninitialized'; (ref($args[0]) eq 'HASH') || confess "Single parameters to inflate() must be a HASH ref"; $data = $args[0]; } } else { $data = { @args }; } my $subclass = $class->_version_class( $class->_get_version($data), $data ); Class::Load::load_class($subclass); $subclass->new_from_data(%$data); } sub new_from_data { shift->new(@_) } sub _get_version { my ( $class, $data ) = @_; if ( exists $data->{jsonrpc} ) { return $data->{jsonrpc}; # presumably 2.0 } elsif ( exists $data->{version} ) { return $data->{version}; # presumably 1.1 } else { return "1.0"; } } sub _version_class { my ( $class, $version, $data ) = @_; my @numbers = ( $version =~ /(\d+)/g ) ; if ( $class eq __PACKAGE__ and $data ) { if ( exists $data->{method} ) { $class = "JSON::RPC::Common::Procedure::Call"; } elsif ( exists $data->{id} or exists $data->{result} ) { $class = "JSON::RPC::Common::Procedure::Return"; } else { croak "Couldn't determine type of message (call or return)"; } } return join( "::", $class, join("_", Version => @numbers) ); } __PACKAGE__ __END__ =pod =head1 NAME JSON::RPC::Common::Message - JSON-RPC message role =head1 VERSION version 0.11 =head1 AUTHOR Yuval Kogman =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2014 by Yuval Kogman and others. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut JSON-RPC-Common-0.11/lib/JSON/RPC/Common/TypeConstraints.pm0000644002053500205350000000222012304200774023061 0ustar dmcbridedmcbride#!/usr/bin/perl package JSON::RPC::Common::TypeConstraints; $JSON::RPC::Common::TypeConstraints::VERSION = '0.11'; # ABSTRACT: Type constraint library use strict; use warnings; use MooseX::Types -declare => [qw(JSONDefined JSONValue JSONContainer)]; use MooseX::Types::Moose qw(Value ArrayRef HashRef Undef); subtype JSONDefined, as Value|ArrayRef|HashRef; subtype JSONValue, as Undef|Value|ArrayRef|HashRef; subtype JSONContainer, as ArrayRef|HashRef; __PACKAGE__ __END__ =pod =head1 NAME JSON::RPC::Common::TypeConstraints - Type constraint library =head1 VERSION version 0.11 =head1 SYNOPSIS use JSON::RPC::Common::TypeConstraints qw(JSONValue); =head1 DESCRIPTION See L =head1 TYPES =over 4 =item JSONDefined C =item JSONValue C =item JSONContainer C =back =head1 AUTHOR Yuval Kogman =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2014 by Yuval Kogman and others. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut JSON-RPC-Common-0.11/lib/JSON/RPC/Common/Procedure/0000755002053500205350000000000012304200774021306 5ustar dmcbridedmcbrideJSON-RPC-Common-0.11/lib/JSON/RPC/Common/Procedure/Return/0000755002053500205350000000000012304200774022565 5ustar dmcbridedmcbrideJSON-RPC-Common-0.11/lib/JSON/RPC/Common/Procedure/Return/Version_2_0.pm0000644002053500205350000000305212304200774025210 0ustar dmcbridedmcbride#!/usr/bin/perl package JSON::RPC::Common::Procedure::Return::Version_2_0; $JSON::RPC::Common::Procedure::Return::Version_2_0::VERSION = '0.11'; use Moose; # ABSTRACT: JSON-RPC 2.0 Procedure Return use JSON::RPC::Common::Procedure::Return::Version_2_0::Error; use namespace::clean -except => [qw(meta)]; extends qw(JSON::RPC::Common::Procedure::Return); has '+version' => ( # default => "2.0", # broken, Moose::Meta::Method::Accessor gens numbers if looks_like_number default => sub { "2.0" }, # init_arg => "jsonrpc", # illegal inherit arg. bah. it's meaningless, so we don't care ); has '+error_class' => ( default => "JSON::RPC::Common::Procedure::Return::Version_2_0::Error", ); sub deflate { my $self = shift; return { jsonrpc => "2.0", ( $self->has_error ? ( error => $self->deflate_error ) : ( result => $self->result ) ), ( $self->has_id ? ( id => $self->id ) : () ), }; } __PACKAGE__->meta->make_immutable; __PACKAGE__ __END__ =pod =head1 NAME JSON::RPC::Common::Procedure::Return::Version_2_0 - JSON-RPC 2.0 Procedure Return =head1 VERSION version 0.11 =head1 SYNOPSIS my $return = $call->return_value("foo"); =head1 DESCRIPTION This class implements procedure returns for JSON::RPC 2.0. See L. =head1 AUTHOR Yuval Kogman =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2014 by Yuval Kogman and others. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut JSON-RPC-Common-0.11/lib/JSON/RPC/Common/Procedure/Return/Version_1_1/0000755002053500205350000000000012304200774024652 5ustar dmcbridedmcbrideJSON-RPC-Common-0.11/lib/JSON/RPC/Common/Procedure/Return/Version_1_1/Error.pm0000644002053500205350000000300212304200774026274 0ustar dmcbridedmcbride#!/usr/bin/perl package JSON::RPC::Common::Procedure::Return::Version_1_1::Error; $JSON::RPC::Common::Procedure::Return::Version_1_1::Error::VERSION = '0.11'; use Moose; # ABSTRACT: JSON-RPC 1.1 error class. use JSON::RPC::Common::TypeConstraints qw(JSONValue); use namespace::clean -except => [qw(meta)]; extends qw(JSON::RPC::Common::Procedure::Return::Error); has '+message' => ( required => 1, ); has '+code' => ( default => 500, ); has name => ( is => "rw", default => "JSONRPCError", # fucking idiots ); sub deflate { my $self = shift; return { name => $self->name, message => $self->message, code => $self->code, ( $self->has_data ? ( error => $self->data ) : () ), }, } __PACKAGE__->meta->make_immutable; __PACKAGE__ __END__ =pod =head1 NAME JSON::RPC::Common::Procedure::Return::Version_1_1::Error - JSON-RPC 1.1 error class. =head1 VERSION version 0.11 =head1 SYNOPSIS my $return_with_error = $call->return_error("foo"); =head1 DESCRIPTION This class implements 1.1 error objects. C and C are mandatory. The C field is named C in the deflated version and C is set to C. How exciting. See L. =head1 AUTHOR Yuval Kogman =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2014 by Yuval Kogman and others. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut JSON-RPC-Common-0.11/lib/JSON/RPC/Common/Procedure/Return/Version_2_0/0000755002053500205350000000000012304200774024652 5ustar dmcbridedmcbrideJSON-RPC-Common-0.11/lib/JSON/RPC/Common/Procedure/Return/Version_2_0/Error.pm0000644002053500205350000000244712304200774026310 0ustar dmcbridedmcbride#!/usr/bin/perl package JSON::RPC::Common::Procedure::Return::Version_2_0::Error; $JSON::RPC::Common::Procedure::Return::Version_2_0::Error::VERSION = '0.11'; use Moose; # ABSTRACT: JSON-RPC 2.0 error class. use JSON::RPC::Common::TypeConstraints qw(JSONValue); use namespace::clean -except => [qw(meta)]; extends qw(JSON::RPC::Common::Procedure::Return::Error); has '+message' => ( required => 1, ); has '+code' => ( default => -32603, ); sub deflate { my $self = shift; return { code => $self->code, message => $self->message, ( $self->has_data ? ( data => $self->data ) : () ), }; } __PACKAGE__->meta->make_immutable; __PACKAGE__ __END__ =pod =head1 NAME JSON::RPC::Common::Procedure::Return::Version_2_0::Error - JSON-RPC 2.0 error class. =head1 VERSION version 0.11 =head1 SYNOPSIS my $return_with_error = $call->return_error("foo"); =head1 DESCRIPTION This class implements 2.0 error objects. C and C are mandatory. See L. =head1 AUTHOR Yuval Kogman =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2014 by Yuval Kogman and others. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut JSON-RPC-Common-0.11/lib/JSON/RPC/Common/Procedure/Return/Version_1_0/0000755002053500205350000000000012304200774024651 5ustar dmcbridedmcbrideJSON-RPC-Common-0.11/lib/JSON/RPC/Common/Procedure/Return/Version_1_0/Error.pm0000644002053500205350000000311112304200774026274 0ustar dmcbridedmcbride#!/usr/bin/perl package JSON::RPC::Common::Procedure::Return::Version_1_0::Error; $JSON::RPC::Common::Procedure::Return::Version_1_0::Error::VERSION = '0.11'; use Moose; # ABSTRACT: JSON-RPC 1.0 error class. use JSON::RPC::Common::TypeConstraints qw(JSONDefined); use namespace::clean -except => [qw(meta)]; extends qw(JSON::RPC::Common::Procedure::Return::Error); has '+data' => ( isa => JSONDefined, ); sub make_data { my $self = shift; return { message => ( $self->has_message ? $self->message : "Unknown error" ), code => $self->code, # might be null }; } sub deflate { my $self = shift; if ( $self->has_data ) { return $self->data; } else { return $self->make_data; } } __PACKAGE__->meta->make_immutable(); __PACKAGE__ __END__ =pod =head1 NAME JSON::RPC::Common::Procedure::Return::Version_1_0::Error - JSON-RPC 1.0 error class. =head1 VERSION version 0.11 =head1 SYNOPSIS my $return_with_error = $call->return_error("foo"); =head1 DESCRIPTION JSON-RPC 1.0 doesn't actually specify what the hell goes in the error field, so in order to make 1.0+2.0 server implementations easy this class is provided as a compatibility layer. Inflating a string instantiates an error with an unset code and the string as the message. See L =head1 AUTHOR Yuval Kogman =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2014 by Yuval Kogman and others. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut JSON-RPC-Common-0.11/lib/JSON/RPC/Common/Procedure/Return/Version_1_0.pm0000644002053500205350000000260012304200774025205 0ustar dmcbridedmcbride#!/usr/bin/perl package JSON::RPC::Common::Procedure::Return::Version_1_0; $JSON::RPC::Common::Procedure::Return::Version_1_0::VERSION = '0.11'; use Moose; # ABSTRACT: JSON-RPC 1.0 error class. use JSON::RPC::Common::Procedure::Return::Version_1_0::Error; use namespace::clean -except => [qw(meta)]; extends qw(JSON::RPC::Common::Procedure::Return); has '+version' => ( # default => "1.0", # broken, Moose::Meta::Method::Accessor gens numbers if looks_like_number default => sub { "1.0" }, ); has '+error_class' => ( default => "JSON::RPC::Common::Procedure::Return::Version_1_0::Error", ); sub deflate { my $self = shift; return { result => ( $self->error ? undef : $self->result ), error => $self->deflate_error, # can be null id => $self->id, # can be null }; } __PACKAGE__->meta->make_immutable; __PACKAGE__ __END__ =pod =head1 NAME JSON::RPC::Common::Procedure::Return::Version_1_0 - JSON-RPC 1.0 error class. =head1 VERSION version 0.11 =head1 SYNOPSIS my $return_with_error = $call->return_error("foo"); =head1 DESCRIPTION See L =head1 AUTHOR Yuval Kogman =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2014 by Yuval Kogman and others. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut JSON-RPC-Common-0.11/lib/JSON/RPC/Common/Procedure/Return/Version_1_1.pm0000644002053500205350000000272112304200774025212 0ustar dmcbridedmcbride#!/usr/bin/perl package JSON::RPC::Common::Procedure::Return::Version_1_1; $JSON::RPC::Common::Procedure::Return::Version_1_1::VERSION = '0.11'; use Moose; # ABSTRACT: JSON-RPC 1.1 Procedure Return use JSON::RPC::Common::Procedure::Return::Version_1_1::Error; use namespace::clean -except => [qw(meta)]; extends qw(JSON::RPC::Common::Procedure::Return); has '+version' => ( # default => "1.1", # broken, Moose::Meta::Method::Accessor gens numbers if looks_like_number default => sub { "1.1" }, ); has '+error_class' => ( default => "JSON::RPC::Common::Procedure::Return::Version_1_1::Error", ); sub deflate { my $self = shift; return { version => "1.1", ( $self->has_error ? ( error => $self->deflate_error ) : ( result => $self->result ) ), ( $self->has_id ? ( id => $self->id ) : () ), }; } __PACKAGE__->meta->make_immutable; __PACKAGE__ __END__ =pod =head1 NAME JSON::RPC::Common::Procedure::Return::Version_1_1 - JSON-RPC 1.1 Procedure Return =head1 VERSION version 0.11 =head1 SYNOPSIS my $return = $call->return_value("foo"); =head1 DESCRIPTION This class implements procedure returns for JSON::RPC 1.1. See L. =head1 AUTHOR Yuval Kogman =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2014 by Yuval Kogman and others. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut JSON-RPC-Common-0.11/lib/JSON/RPC/Common/Procedure/Return/Error.pm0000644002053500205350000000544512304200774024224 0ustar dmcbridedmcbride#!/usr/bin/perl package JSON::RPC::Common::Procedure::Return::Error; $JSON::RPC::Common::Procedure::Return::Error::VERSION = '0.11'; use Moose; # ABSTRACT: Base class for JSON-RPC errors use JSON::RPC::Common::TypeConstraints qw(JSONValue); use namespace::clean -except => [qw(meta)]; sub new_dwim { my ( $class, @args ) = @_; if ( @args == 1 ) { if ( blessed($args[0]) and $args[0]->isa($class) ) { return $args[0]; } } $class->inflate(@args); } sub inflate { my ( $class, @args ) = @_; my $data; if (@args == 1 and defined $args[0] and (ref($args[0])||'') eq 'HASH') { $data = { %{ $args[0] } }; } else { if ( @args % 2 == 1 ) { unshift @args, "message"; } $data = { @args }; } my %constructor_args; foreach my $arg ( qw(message code) ) { $constructor_args{$arg} = delete $data->{$arg} if exists $data->{$arg}; } if ( keys %$data ) { $constructor_args{data} = (join(" ", keys %$data) eq 'data' ? $data->{data} : $data); } $class->new(%constructor_args); } has data => ( isa => JSONValue, is => "rw", predicate => "has_data", ); has message => ( isa => "Str", is => "rw", predicate => "has_message", ); has code => ( isa => "Int", is => "rw", predicate => "has_code", ); # FIXME delegate to a dictionary sub http_status { 500 } __PACKAGE__->meta->make_immutable(); __PACKAGE__ __END__ =pod =head1 NAME JSON::RPC::Common::Procedure::Return::Error - Base class for JSON-RPC errors =head1 VERSION version 0.11 =head1 SYNOPSIS use JSON::RPC::Common::Procedure::Return::Error; my $error = JSON::RPC::Common::Procedure::Return::Error->new( message => "foo", code => "bah", ); # or construct a return with an error from a call: my $return = $call->return_error("foo"); $return->error->message; =head1 DESCRIPTION This is a base class for all version specific error implementations. =head1 ATTRIBUTES =over 4 =item code =item message =item data These are the three common JSON-RPC error fields. In JSON-RPC 1.1 C is known as C, and in 1.0 none of this is specced at all. See the version specific subclasses for various behaviors. Code is an integer, and message is a string. =back =head1 METHODS =over 4 =item new_dwim Convenience constructor used by L. Will return an object if that's the argument, and otherwise construct an error. =item inflate Create an error object from JSON data (not text). In order to maximize compatibility this inflation routine is very liberal in what it accepts. =back =head1 AUTHOR Yuval Kogman =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2014 by Yuval Kogman and others. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut JSON-RPC-Common-0.11/lib/JSON/RPC/Common/Procedure/Call.pm0000644002053500205350000001163212304200774022522 0ustar dmcbridedmcbride#!/usr/bin/perl package JSON::RPC::Common::Procedure::Call; $JSON::RPC::Common::Procedure::Call::VERSION = '0.11'; use Moose; # ABSTRACT: JSON RPC Procedure Call base class. use Try::Tiny; use JSON::RPC::Common::TypeConstraints qw(JSONValue); use JSON::RPC::Common::Procedure::Return; use Carp qw(croak); use namespace::clean -except => [qw(meta)]; with qw(JSON::RPC::Common::Message); has return_class => ( isa => "ClassName", is => "rw", default => "JSON::RPC::Common::Procedure::Return", ); has error_class => ( isa => "ClassName", is => "rw", default => "JSON::RPC::Common::Procedure::Return::Error", ); has version => ( isa => "Str", is => "rw", predicate => "has_version", ); has method => ( isa => "Str", is => "rw", required => 1, ); has id => ( isa => JSONValue, is => "rw", predicate => "has_id", ); has params => ( isa => "Ref", is => "rw", predicate => "has_params", ); sub deflate_version { return (); } sub deflate_method { my $self = shift; return ( method => $self->method ); } sub deflate_id { my $self = shift; if ( $self->has_id ) { return ( id => $self->id ); } else { return (); } } sub deflate_params { my $self = shift; if ( $self->has_params ) { return ( params => $self->params ); } else { return (); } } sub deflate { my $self = shift; return { $self->deflate_version, $self->deflate_method, $self->deflate_id, $self->deflate_params, }; } sub is_service { 0 } sub is_notification { my $self = shift; return not $self->has_id; } sub params_list { my $self = shift; my $p = $self->params; if ( ref $p eq 'HASH' ) { return %$p; } elsif ( ref $p eq 'ARRAY' ) { return @$p; } else { return $p; # FIXME error? } } sub call { my ( $self, $invocant, @args ) = @_; die "No invocant provided" unless blessed($invocant); my $method = $self->method; my $error; my @res = try { $invocant->$method( $self->params_list, @args ) } catch { $error = $_; }; if ($error) { $self->return_error(message => $error); } else { $self->return_result(@res); } } sub create_return { my ( $self, @args ) = @_; $self->return_class->new( error_class => $self->error_class, ( $self->has_id ? ( id => $self->id ) : () ), @args, ); } sub return_error { my ( $self, @args ) = @_; $self->create_return( error => $self->error_class->new_dwim(@args) ); } sub return_result { my ( $self, @res ) = @_; my $res = @res == 1 ? $res[0] : \@res; $self->create_return( result => $res ); } __PACKAGE__->meta->make_immutable; __PACKAGE__ __END__ =pod =head1 NAME JSON::RPC::Common::Procedure::Call - JSON RPC Procedure Call base class. =head1 VERSION version 0.11 =head1 SYNOPSIS use JSON::RPC::Common::Procedure::Call; my $req = JSON::RPC::Common::Procedure::Call->inflate({ ... }); warn "HALLO JSONRPC VERSION " . $req->version; =head1 DESCRIPTION A JSON-RPC Procedure Call (ed: *rolls eys*, what was wrong with "request"?) is either a notification or a method invocation in JSON-PRC. See L for more details. =head1 ATTRIBUTES All attributes are read only unless otherwise specified. =over 4 =item version =item id The request ID. Used to correlate a request to a response. =item method The name of the method to invoke. =item params Returns a reference to the parameters hash or array. =item return_class =item error_class The classes to instantiate the response objects. These vary per subclass. =back =head1 METHODS =over 4 =item inflate A factory constructor. Delegates to C on a subclass based on the protocol version. This is the recommended constructor. =item deflate Flatten to JSON data =item new The actual constructor. Not intended for normal use on this class, you should use a subclass most of the time. Calling C<< JSON::RPC::Common::Procedure::Call->new >> will construct a call with an undefined version, which cannot be deflated (and thus sent over the wire). This is still useful for testing your own code's RPC hanlding, so this is not allowed. =item params_list Dereferences C regardless of representation. Returns a list of positionals or a key/value list. =item return_result $result =item return_error %error_params Create a new L with or without an error. =item is_notification Whether this request is a notification (a method that does not need a response). =item is_service Whether this request is a JSON-RPC 1.1 service method (e.g. C). This method is always false for 1.0 and 2.0. =item call $obj A convenience method to invoke the call on C<$obj> and create a new return with the return value. =back =head1 AUTHOR Yuval Kogman =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2014 by Yuval Kogman and others. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut JSON-RPC-Common-0.11/lib/JSON/RPC/Common/Procedure/Call/0000755002053500205350000000000012304200774022161 5ustar dmcbridedmcbrideJSON-RPC-Common-0.11/lib/JSON/RPC/Common/Procedure/Call/Version_2_0.pm0000644002053500205350000000372012304200774024606 0ustar dmcbridedmcbride#!/usr/bin/perl package JSON::RPC::Common::Procedure::Call::Version_2_0; $JSON::RPC::Common::Procedure::Call::Version_2_0::VERSION = '0.11'; use Moose; # ABSTRACT: JSON-RPC 2.0 Procedure Call use JSON::RPC::Common::TypeConstraints qw(JSONContainer); use JSON::RPC::Common::Procedure::Return::Version_2_0; use namespace::clean -except => [qw(meta)]; extends qw(JSON::RPC::Common::Procedure::Call); has '+version' => ( # default => "2.0", # broken, Moose::Meta::Method::Accessor gens numbers if looks_like_number default => sub { "2.0" }, # init_arg => "jsonrpc", # illegal inherit arg. bah. it's meaningless, so we don't care ); has '+params' => ( isa => JSONContainer, ); has '+return_class' => ( default => "JSON::RPC::Common::Procedure::Return::Version_2_0", ); has '+error_class' => ( default => "JSON::RPC::Common::Procedure::Return::Version_2_0::Error", ); sub deflate_version { my $self = shift; return ( jsonrpc => $self->version ); } __PACKAGE__->meta->make_immutable; __PACKAGE__ __END__ =pod =head1 NAME JSON::RPC::Common::Procedure::Call::Version_2_0 - JSON-RPC 2.0 Procedure Call =head1 VERSION version 0.11 =head1 SYNOPSIS use JSON::RPC::Common::Procedure::Call; my $req = JSON::RPC::Common::Procedure::Call->inflate({ jsonrpc => "2.0", id => "oink", params => { foo => "bar" }, }); =head1 DESCRIPTION This class implements JSON-RPC Procedure Call objects according to the 2.0 specification proposal: L. JSON RPC 2.0 reinstate notifications, and allow the same format for parameters. Requests are considered notifications only when the C field is missing, not when it's null. =head1 AUTHOR Yuval Kogman =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2014 by Yuval Kogman and others. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut JSON-RPC-Common-0.11/lib/JSON/RPC/Common/Procedure/Call/Version_1_0.pm0000644002053500205350000000356512304200774024614 0ustar dmcbridedmcbride#!/usr/bin/perl package JSON::RPC::Common::Procedure::Call::Version_1_0; $JSON::RPC::Common::Procedure::Call::Version_1_0::VERSION = '0.11'; use Moose; # ABSTRACT: JSON-RPC 1.0 request use JSON::RPC::Common::Procedure::Return::Version_1_0; use namespace::clean -except => [qw(meta)]; extends qw(JSON::RPC::Common::Procedure::Call); has '+version' => ( # default => "1.0", # broken, Moose::Meta::Method::Accessor gens numbers if looks_like_number default => sub { "1.0" }, ); has '+params' => ( isa => "ArrayRef", required => 1, ); has '+id' => ( required => 1, ); has '+return_class' => ( default => "JSON::RPC::Common::Procedure::Return::Version_1_0", ); has '+error_class' => ( default => "JSON::RPC::Common::Procedure::Return::Version_1_0::Error", ); sub is_notification { my $self = shift; return not defined $self->id; } sub deflate_params { my $self = shift; return ( params => $self->params ); } sub deflate_id { my $self = shift; return ( id => $self->id ); # never omitted, can be null instead } __PACKAGE__->meta->make_immutable; __PACKAGE__ __END__ =pod =head1 NAME JSON::RPC::Common::Procedure::Call::Version_1_0 - JSON-RPC 1.0 request =head1 VERSION version 0.11 =head1 SYNOPSIS use JSON::RPC::Common::Procedure::Call; my $req = JSON::RPC::Common::Procedure::Call->inflate({ # 1.0 doesn't specify the version id => "oink", params => [ 1 .. 3 ], }); =head1 DESCRIPTION This class implements requests according to the JSON-RPC 1.0 spec: L. JSON-RPC 1.0 requests are considered notifications if the C is null. =head1 AUTHOR Yuval Kogman =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2014 by Yuval Kogman and others. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut JSON-RPC-Common-0.11/lib/JSON/RPC/Common/Procedure/Call/Version_1_1.pm0000644002053500205350000000636412304200774024615 0ustar dmcbridedmcbride#!/usr/bin/perl package JSON::RPC::Common::Procedure::Call::Version_1_1; $JSON::RPC::Common::Procedure::Call::Version_1_1::VERSION = '0.11'; use Moose; # ABSTRACT: JSON-RPC 1.1 Procedure Call use MRO::Compat; use JSON::RPC::Common::TypeConstraints qw(JSONContainer); use JSON::RPC::Common::Procedure::Return::Version_1_1; use Carp qw(croak); use namespace::clean -except => [qw(meta)]; extends qw(JSON::RPC::Common::Procedure::Call); sub BUILDARGS { my ( $self, @args ) = @_; my $params = $self->next::method(@args); if ( exists $params->{kwparams} ) { if ( exists $params->{params} ) { croak "params and kwparams are mutually exclusive"; } else { $params->{params} = delete $params->{kwparams}; } $params->{alt_spec} = 1 unless exists $params->{alt_spec}; } return $params; } has '+version' => ( # default => "1.1", # broken, Moose::Meta::Method::Accessor gens numbers if looks_like_number default => sub { "1.1" }, ); has alt_spec => ( isa => "Bool", is => "rw", default => 0, ); has '+params' => ( isa => JSONContainer, ); has '+return_class' => ( default => "JSON::RPC::Common::Procedure::Return::Version_1_1", ); has '+return_class' => ( default => "JSON::RPC::Common::Procedure::Return::Version_1_1", ); has '+error_class' => ( default => "JSON::RPC::Common::Procedure::Return::Version_1_1::Error", ); sub is_notification { 0 } sub is_service { my $self = shift; $self->method =~ /^system\./; } sub deflate_version { my $self = shift; return ( version => $self->version ) ; } sub deflate_params { my $self = shift; if ( $self->has_params ) { my $params = $self->params; # JSON-RPC 1.1 alt specifies that named params go in kwparams. YUCK! if ( ref($params) eq 'HASH' and $self->alt_spec ) { return ( kwparams => $params ); } return ( params => $params ); } else { return (); } } __PACKAGE__->meta->make_immutable; __PACKAGE__ __END__ =pod =head1 NAME JSON::RPC::Common::Procedure::Call::Version_1_1 - JSON-RPC 1.1 Procedure Call =head1 VERSION version 0.11 =head1 SYNOPSIS use JSON::RPC::Common::Procedure::Call; my $req = JSON::RPC::Common::Procedure::Call->inflate({ version => "1.1", id => "oink", params => { foo => "bar" }, }); =head1 DESCRIPTION This class implements JSON-RPC 1.1 Procedure Calls according to the 1.1 working draft: L. JSON RPC 1.1 requests are never notifications, and accept either hash references or array references as parameters. Note that the alternative JSON RPC 1.1 proposition is also be supported: L. C is accepted as an alias to C, but C will also accept hash references. However, to simplify things, C and C are mutually exclusive, since Perl doesn't have strong support for named params. The alternative spec does not offer notifications (it is a TODO item), so currently C always returns false. =head1 AUTHOR Yuval Kogman =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2014 by Yuval Kogman and others. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut JSON-RPC-Common-0.11/lib/JSON/RPC/Common/Procedure/Return.pm0000644002053500205350000000733512304200774023133 0ustar dmcbridedmcbride#!/usr/bin/perl package JSON::RPC::Common::Procedure::Return; $JSON::RPC::Common::Procedure::Return::VERSION = '0.11'; use Moose; # ABSTRACT: JSON-RPC procedure return class use Carp qw(croak); use JSON::RPC::Common::TypeConstraints qw(JSONValue); use JSON::RPC::Common::Procedure::Return::Error; use namespace::clean -except => [qw(meta)]; with qw(JSON::RPC::Common::Message); around new_from_data => sub { my $next = shift; my ( $class, %args ) = @_; if ( defined(my $error = delete $args{error}) ) { $args{error} = $class->inflate_error($error, %args); } return $class->$next(%args); }; has version => ( isa => "Str", is => "rw", predicate => "has_version", ); has result => ( isa => "Any", is => "rw", predicate => "has_result", ); has id => ( isa => JSONValue, is => "rw", predicate => "has_id", ); has error_class => ( isa => "ClassName", is => "rw", default => "JSON::RPC::Common::Procedure::Return::Error", ); has error => ( isa => "JSON::RPC::Common::Procedure::Return::Error", is => "rw", predicate => "has_error", ); sub deflate { my $self = shift; my $version = $self->version; $version = "undefined" unless defined $version; croak "Deflating a procedure return of the class " . ref($self) . " is not supported (version is $version)"; } sub deflate_error { my $self = shift; if ( my $error = $self->error ) { return $error->deflate; } else { return undef; } } sub inflate_error { my ( $self, $error ) = @_; my $error_class = ref $self ? $self->error_class : $self->meta->find_attribute_by_name("error_class")->default; $error_class->inflate($error); } sub set_error { my ( $self, @args ) = @_; $self->error( $self->create_error(@args) ); } sub create_error { my ( $self, @args ) = @_; $self->error_class->new_dwim(@args); } __PACKAGE__->meta->make_immutable; __PACKAGE__ __END__ =pod =head1 NAME JSON::RPC::Common::Procedure::Return - JSON-RPC procedure return class =head1 VERSION version 0.11 =head1 SYNOPSIS use JSON::RPC::Common::Procedure::Return; # create a return from a call, retaining the ID my $return = $call->return_result("foo"); # inflate gets a version specific class my $return = JSON::RPC::Common::Procedure::Return->inflate( version => "2.0", result => "foo", id => $id, ); # you can specify a return with an error, it's just an attribute my $return = JSON::RPC::Common::Procedure::Return->new( error => ..., ); =head1 DESCRIPTION This class abstracts JSON-RPC procedure returns (results). Version specific implementation are provided as well. =head1 ATTRIBUTES =over 4 =item id The ID of the call this is a result for. Results with no ID are typically error results for parse fails, when the call ID could never be determined. =item result The JSON data that is the result of the call, if any. =item error The error, if any. This is a L object (or a version specific subclass). =item error_class The error class to use when instantiating errors. =back =head1 METHODS =over 4 =item inflate =item deflate Go to and from JSON data. =item inflate_error =item deflate_error Helpers for managing the error sub object. =item set_error Calls C with it's arguments and sets the error to that. E.g. $res->set_error("foo"); $res->error->message; # "foo" =item create_error Instantiate a new error of class L using L. =back =head1 AUTHOR Yuval Kogman =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2014 by Yuval Kogman and others. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut JSON-RPC-Common-0.11/lib/JSON/RPC/Common/Marshal/0000755002053500205350000000000012304200774020745 5ustar dmcbridedmcbrideJSON-RPC-Common-0.11/lib/JSON/RPC/Common/Marshal/HTTP.pm0000644002053500205350000003324112304200774022065 0ustar dmcbridedmcbride#!/usr/bin/perl package JSON::RPC::Common::Marshal::HTTP; $JSON::RPC::Common::Marshal::HTTP::VERSION = '0.11'; use Moose; # ABSTRACT: Convert L and L to/from L calls and returns. use Carp qw(croak); use Try::Tiny; use URI::QueryParam; use MIME::Base64 (); use HTTP::Response; use namespace::clean -except => [qw(meta)]; extends qw(JSON::RPC::Common::Marshal::Text); sub _build_json { JSON->new->utf8(1); } has prefer_get => ( isa => "Bool", is => "rw", default => 0, ); has rest_style_methods => ( isa => "Bool", is => "rw", default => 1, ); has prefer_encoded_get => ( isa => "Bool", is => "rw", default => 1, ); has expand => ( isa => "Bool", is => "rw", default => 0, ); has expander => ( isa => "ClassName|Object", lazy_build => 1, handles => [qw(expand_hash collapse_hash)], ); sub _build_expander { require CGI::Expand; return "CGI::Expand"; } has user_agent => ( isa => "Str", is => "rw", lazy_build => 1, ); sub _build_user_agent { my $self = shift; require JSON::RPC::Common; join(" ", ref($self), $JSON::RPC::Common::VERSION), } has content_type => ( isa => "Str", is => "rw", predicate => "has_content_type", ); has content_types => ( isa => "HashRef[Str]", is => "rw", lazy_build => 1, ); sub _build_content_types { return { "1.0" => "application/json", "1.1" => "application/json", "2.0" => "application/json-rpc", }; } has accept_content_type => ( isa => "Str", is => "rw", predicate => "has_accept_content_type", ); has accept_content_types => ( isa => "HashRef[Str]", is => "rw", lazy_build => 1, ); sub _build_accept_content_types { return { "1.0" => "application/json", "1.1" => "application/json", "2.0" => "application/json-rpc", }; } sub get_content_type { my ( $self, $obj ) = @_; if ( $self->has_content_type ) { return $self->content_type; } else { return $self->content_types->{ $obj->version || "2.0" }; } } sub get_accept_content_type { my ( $self, $obj ) = @_; if ( $self->has_accept_content_type ) { return $self->accept_content_type; } else { return $self->accept_content_types->{ $obj->version || "2.0" }; } } sub call_to_request { my ( $self, $call, %args ) = @_; $args{prefer_get} = $self->prefer_get unless exists $args{prefer_get}; if ( $args{prefer_get} ) { return $self->call_to_get_request($call, %args); } else { return $self->call_to_post_request($call, %args); } } sub call_to_post_request { my ( $self, $call, @args ) = @_; my $uri = $self->call_reconstruct_uri_base($call, @args); my $encoded = $self->call_to_json($call); my $headers = HTTP::Headers->new( User_Agent => $self->user_agent, Content_Type => $self->get_content_type($call), Accept => $self->get_accept_content_type($call), Content_Length => length($encoded), ); return HTTP::Request->new( POST => $uri, $headers, $encoded ); } sub call_to_get_request { my ( $self, $call, @args ) = @_; my $uri = $self->call_to_uri($call, @args); my $headers = HTTP::Headers->new( User_Agent => $self->user_agent, Accept => $self->get_accept_content_type($call), ); HTTP::Request->new( GET => $uri, $headers ); } sub call_to_uri { my ( $self, $call, %args ) = @_; no warnings 'uninitialized'; my $prefer_encoded_get = exists $args{encoded} ? $args{encoded} : ( $call->version eq '2.0' || $self->prefer_encoded_get ); if ( $prefer_encoded_get ) { return $self->call_to_encoded_uri($call, %args); } else { return $self->call_to_query_uri($call, %args); } } sub call_reconstruct_uri_base { my ( $self, $call, %args ) = @_; 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); my ( $method, $params, $id ) = delete @{ $deflated }{qw(method params id)}; my $encoded = $self->encode_base64( $self->encode($params) ); $uri->query_param( params => $encoded ); $uri->query_param( method => $method ); $uri->query_param( id => $id ) if $call->has_id; return $uri; } sub call_to_query_uri { my ( $self, $call, %args ) = @_; my $uri = $self->call_reconstruct_uri_base($call, %args); my $deflated = $self->deflate_call( $call ); my ( $method, $params, $id ) = delete @{ $deflated }{qw(method params id)}; $params = $self->collapse_query_params($params); $uri->query_form( %$params, id => $id ); if ( exists $args{rest_style_methods} ? $args{rest_style_methods} : $self->rest_style_methods ) { my $path = $uri->path; $path =~ s{/?$}{"/" . $method}e; # add method, remove double trailing slash $uri->path($path); } else { $uri->query_param( method => $method ); } return $uri; } sub request_to_call { my ( $self, $request, @args ) = @_; my $req_method = lc( $request->method . "_request_to_call" ); if ( my $code = $self->can($req_method) ) { $self->$code($request, @args); } else { croak "Unsupported HTTP request method " . $request->method; } } sub get_request_to_call { my ( $self, $request, @args ) = @_; $self->uri_to_call(request => $request, @args); } sub uri_to_call { 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 ); } else { return $self->query_uri_to_call( $uri, %args ); } } sub decode_base64 { my ( $self, $base64 ) = @_; MIME::Base64::decode_base64($base64); } sub encode_base64 { my ( $self, $base64 ) = @_; MIME::Base64::encode_base64($base64); } # the sane way, 1.1-alt sub encoded_uri_to_call { my ( $self, $uri, @args ) = @_; my $params = $uri->query_form_hash; # the 'params' URI param is encoded as JSON, inflate it my %rpc = %$params; $rpc{version} ||= "2.0"; for my $params ( $rpc{params} ) { # try as unencoded JSON first if ( my $data = try { $self->decode($params) } ) { $params = $data; } else { my $json = $self->decode_base64($params) || croak "params are not Base64 encoded"; $params = $self->decode($json); } } $self->inflate_call(\%rpc); } # the less sane but occasionally useful way, 1.1-wd sub query_uri_to_call { my ( $self, $uri, %args ) = @_; my $params = $uri->query_form_hash; my %rpc = ( params => $params ); foreach my $key (qw(version jsonrpc method id) ) { if ( exists $params->{$key} ) { $rpc{$key} = delete $params->{$key}; } } 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); $self->inflate_call(\%rpc); } sub expand_query_params { my ( $self, $params, @args ) = @_; if ( $self->expand ) { return $self->expand_hash($params); } else { return $params; } } sub collapse_query_params { my ( $self, $params, $request, @args ) = @_; if ( $self->expand ) { return $self->collapse_hash($params); } else { return $params; } } sub post_request_to_call { my ( $self, $request ) = @_; $self->json_to_call( $request->content ); } sub write_result_to_response { my ( $self, $result, $response, @args ) = @_; my %args = $self->result_to_response_params($result); foreach my $key ( keys %args ) { if ( $response->can($key) ) { $response->$key(delete $args{$key}); } } if (my @keys = keys %args) { croak "Unhandled response params: " . join ' ', @keys; } return 1; } sub response_to_result { my ( $self, $response ) = @_; if ( $response->is_success ) { $self->response_to_result_success($response); } else { $self->response_to_result_error($response); } } sub response_to_result_success { my ( $self, $response ) = @_; $self->json_to_return( $response->content ); } sub response_to_result_error { my ( $self, $response ) = @_; my $res = $self->json_to_return( $response->content ); unless ( $res->has_error ) { $res->set_error( message => $response->message, code => $response->code, # FIXME dictionary data => { response => $response, } ); } return $res; } sub result_to_response { my ( $self, $result ) = @_; $self->create_http_response( $self->result_to_response_headers($result) ); } sub create_http_response { my ( $self, %args ) = @_; my ( $body, $status ) = delete @args{qw(body status)}; HTTP::Response->new( $status, undef, HTTP::Headers->new(%args), $body, ); } sub result_to_response_headers { my ( $self, $result ) = @_; my $body = $self->encode($result->deflate); return ( status => ( $result->has_error ? $result->error->http_status : 200 ), Content_Type => $self->get_content_type($result), Content_Length => length($body), # http://json-rpc.org/wd/JSON-RPC-1-1-WD-20060807.html#ResponseHeaders body => $body, ); } sub result_to_response_params { my ( $self, $result ) = @_; my %headers = $self->result_to_response_headers($result); $headers{content_type} = delete $headers{Content_Type}; $headers{content_length} = delete $headers{Content_Length}; return %headers; } __PACKAGE__->meta->make_immutable(); __PACKAGE__ __END__ =pod =head1 NAME JSON::RPC::Common::Marshal::HTTP - Convert L and L to/from L calls and returns. =head1 VERSION version 0.11 =head1 SYNOPSIS use JSON::RPC::Common::Marshal::HTTP; my $m = JSON::RPC::Common::Marshal::HTTP->new; my $call = $m->request_to_call($http_request); my $res = $call->call($object); my $http_response = $m->result_to_response($res); =head1 DESCRIPTION This object provides marshalling routines to convert calls and returns to and from L and L objects. =head1 ATTRIBUTES =over 4 =item prefer_get When encoding a call into a request, prefer GET. Not reccomended. =item rest_style_methods When encoding a GET request, use REST style URI formatting (the method is part of the path, not a parameter). =item prefer_encoded_get When set and a C param exists, decode it as Base 64 encoded JSON and use that as the parameters instead of the query parameters. See L. =item user_agent Defaults to the marshal object's class name and the L version number. =item content_type =item accept_content_type =item content_types =item accept_content_types When explicitly set these are the values of the C and C headers to set. Otherwise they will default to C with calls/returns version 1.0 and 1.1, and C with 2.0 objects. =item expand Whether or not to use an expander on C style calls. =item expander An instance of L or a look alike to use for C parameter expansion. =back =head1 METHODS =over 4 =item request_to_call $http_request =item post_request_to_call $http_request =item get_request_to_call $http_request Convert an L to a L. Depending on what style of request it is, C will delegate to a variant method. Get requests call C =item uri_to_call $uri =item encoded_uri_to_call $uri =item query_uri_to_call $uri Parse a call from a GET request's URI. =item result_to_response $return Convert a L to an L. =item write_result_to_response $result, $response Write the result into an object like L. =item response_to_result $http_response =item response_to_result_success $http_response =item response_to_result_error $http_response Convert an L to a L. A variant is chosen based on C. The error handler will ensure that L is set. =item call_to_request $call, %args =item call_to_get_request $call, %args =item call_to_post_request $call, %args =item call_to_uri $call, %args =item call_to_encoded_uri $call, %args =item call_to_query_uri $call, %args Convert a call to a request (or just a URI for GET requests). The arguments can contain a C parameter, which is the base of the request. With GET requests, under C that URI's path will be appended, and otherwise parameters will just be added. POST requests do not cloen and alter the URI. If no URI is provided as an argument, C will be used. The flags C and C can also be passed to C to alter the type of request to be generated. =item collapse_query_params =item expand_query_params Only used for query encoded GET requests. If C is set will cause expansion of the params. Otherwise it's a noop. Subclass and override to process query params into RPC params as necessary. Note that this is B in any of the JSON-RPC specs. =back =head1 AUTHOR Yuval Kogman =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2014 by Yuval Kogman and others. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut JSON-RPC-Common-0.11/lib/JSON/RPC/Common/Marshal/Text.pm0000644002053500205350000000620212304200774022227 0ustar dmcbridedmcbride#!/usr/bin/perl package JSON::RPC::Common::Marshal::Text; $JSON::RPC::Common::Marshal::Text::VERSION = '0.11'; use Moose; # ABSTRACT: JSON text marshalling for L. use Carp qw(croak); use JSON (); use JSON::RPC::Common::Message; use JSON::RPC::Common::Procedure::Call; use JSON::RPC::Common::Procedure::Return; use namespace::clean -except => [qw(meta)]; has json => ( isa => "Object", is => "rw", handles => [qw(encode decode)], lazy_build => 1, ); sub _build_json { JSON->new; } has message_class => ( isa => "ClassName", is => "rw", default => "JSON::RPC::Common::Message", handles => { "inflate_message" => "inflate" }, ); has call_class => ( isa => "ClassName", is => "rw", default => "JSON::RPC::Common::Procedure::Call", handles => { "inflate_call" => "inflate" }, ); has return_class => ( isa => "ClassName", is => "rw", default => "JSON::RPC::Common::Procedure::Return", handles => { "inflate_return" => "inflate" }, ); sub deflate_call { my ( $self, $call ) = @_; $call->deflate; } sub deflate_return { my ( $self, $return ) = @_; $return->deflate; } sub message_to_json { my ( $self, $message ) = @_; if ( $message->isa("JSON::RPC::Common::Procedure::Call") ) { $self->call_to_json($message); } elsif ( $message->isa("JSON::RPC::Common::Procedure::Return") ) { $self->return_to_json($message); } else { croak "I dunno wtf $message is"; } } sub json_to_message { my ( $self, $json ) = @_; $self->inflate_message( $self->decode($json) ); } sub call_to_json { my ( $self, $call ) = @_; $self->encode( $self->deflate_call($call) ); } sub return_to_json { my ( $self, $ret ) = @_; $self->encode( $self->deflate_return($ret) ); } sub json_to_call { my ( $self, $json ) = @_; $self->inflate_call( $self->decode($json) ); } sub json_to_return { my ( $self, $json ) = @_; $self->inflate_return( $self->decode($json) ); } __PACKAGE__->meta->make_immutable(); __PACKAGE__ __END__ =pod =head1 NAME JSON::RPC::Common::Marshal::Text - JSON text marshalling for L. =head1 VERSION version 0.11 =head1 SYNOPSIS use JSON::RPC::Common::Marshal::Text; my $m = JSON::RPC::Common::Marshal::Text->new; my $return_obj = $m->json_to_return($json_text); =head1 DESCRIPTION This object serializes L and L objects into JSON text using the L module. =head1 ATTRIBUTES =over 4 =item json The L object to use. A default one will be created if not specified. =item call_class =item return_class The classes to call C on. Defaults to L and L. =back =head1 METHODS =over 4 =item call_to_json =item json_to_call =item return_to_json =item json_to_return These methods do the conversion from objects to json and vice versa. =back =head1 AUTHOR Yuval Kogman =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2014 by Yuval Kogman and others. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut JSON-RPC-Common-0.11/lib/JSON/RPC/Common.pm0000644002053500205350000001267012304200774017722 0ustar dmcbridedmcbride#!/usr/bin/perl package JSON::RPC::Common; $JSON::RPC::Common::VERSION = '0.11'; # ABSTRACT: Transport agnostic JSON RPC helper objects __PACKAGE__ __END__ =pod =head1 NAME JSON::RPC::Common - Transport agnostic JSON RPC helper objects =head1 VERSION version 0.11 =head1 SYNOPSIS # this is a simplistic example # you probably want to use L instead for # something like this. use JSON::RPC::Common::Procedure::Call; # deserialize whatever json text you have into json data: my $req = from_json($request_body); # inflate it and get a call object: my $call = JSON::RPC::Common::Procedure::Call->inflate($req); warn $call->version; # this will create a result object of the correct class/version/etc # "value" is the return result, regardless of version my $res = $call->return_result("value"); # finally, convert back to json text: print to_json($res->deflate); =head1 DESCRIPTION This module provides abstractions for JSON-RPC 1.0, 1.1 (both variations) and 2.0 (formerly 1.2) Procedure Call and Procedure Return objects (formerly known as request and result), along with error objects. It also provides marshalling objects to convert the model objects into JSON text and HTTP requests/responses. This module does not concern itself with the transport layer at all, so the JSON-RPC 1.1 and the alternative specification, which are very different on that level are implemented with the same class. =head1 RANT While JSON-RPC 1.0 and JSON-RPC 2.0 are beautifully simple, the JSON-RPC 1.1 working draft, is most definitely not. It is a convoluted protocol, and also demands a lot more complexity from the responders on the server side (server side introspection (C), strange things relating to positional vs. named params...). Unfortunately it appears that JSON-RPC 1.1 is the most popular variant. Since the client essentially chooses the version of the RPC to be used, for public APIs I reccomend that all versions be supported, but be aware that a 1.1-WD server "MUST" implement service description in order to be in compliance. Anyway, enough bitching. I suggest making your servers 1.0+2.0, and your clients 2.0. =head1 CLASSES There are various classes provided by L. They are designed for high reusability. All the classes are transport and representation agnostic except for L and L which are completely optional. =head2 L This class and its subclasses implement Procedure Calls (requests) for JSON-RPC 1.0, 1.1WD, 1.1-alt and 2.0. =head2 L This class and its subclasses implement Procedure Returns (results) for JSON-RPC 1.0, 1.1WD, 1.1-alt and 2.0. =head2 L This class and its subclasses implement Procedure Return error objects for JSON-RPC 1.0, 1.1WD, 1.1-alt and 2.0. =head2 L A filter object that uses L to serialize procedure calls and returns to JSON text, including JSON-RPC standard error handling for deserialization failure. =head2 L A subclass of L with additional methods for marshaling between Ls and L and L and L. Also knows how to handle JSON-RPC 1.1 C encoded requests (for all versions), providing RESTish call semantics. =head1 TODO =over 4 =item * L, a generic dispatch table based handler, useful for when you don't want to just blindly call methods on certain objects using L. =item * L, a class that will provide dictionaries of error codes for JSON-RPC 1.1 and 1.1-alt/2.0. =item * An object model for JSON-RPC 1.1 service description. SMD is required by most JSON-RPC 1.1 over HTTP clients. Since this is generally static, for now you can write one manually, see L for an example =item * L class to SMD translator =item * L enabled objects can serialize themselves into JSON, and should DWIM when used. JSON-RPC 1.0 class hints could be used here too. =item * Convert to L for smaller deps and faster load time. Need to find a solution for roles and type constraints. Neither is relied on heavily. =back =head1 SEE ALSO =head2 On the Intertubes =over 4 =item JSON-RPC 1.0 specification L =item JSON-RPC 1.1 working draft L =item JSON-RPC 1.1 alternative specification proposal L =item JSON-RPC 2.0 specification proposal L =item Simplified encoding of JSON-RPC over HTTP L =back =head2 On the CPAN L, L, L, L, L =head1 AUTHOR Yuval Kogman =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2014 by Yuval Kogman and others. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut JSON-RPC-Common-0.11/README0000644002053500205350000000061012304200774015040 0ustar dmcbridedmcbride This archive contains the distribution JSON-RPC-Common, version 0.11: Transport agnostic JSON RPC helper objects This software is copyright (c) 2014 by Yuval Kogman and others. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. This README file was generated by Dist::Zilla::Plugin::Readme v5.012. JSON-RPC-Common-0.11/Changes0000644002053500205350000000203112304200774015452 0ustar dmcbridedmcbride0.11 2014-02-28 - Fix tests for 5.18 - Call to Class::MOP::load_class deprecated, call Class::Load directly 0.10 2011-02-16 - bump dep on n::c 0.09 2011-02-16 - fix write_result_to_response 0.08 - swap all evals for Try::Tiny 0.07 - Fix deflation of 1.0 results (which require "error":null) - Always provide Content-Length in HTTP responses 0.06 - Encode/decode UTF8 automatically in the HTTP marshal 0.05 - Fix MooseX::Types related warnings 0.04 - Added support for path_info/base_path in Marshal::HTTP, for complex method names under rest_style_methods - Improved error support, but not 100% there yet, when Moose has custom exception object support we will be able to generate much better errors - fixed JSON::RPC::Common::Procedure::Call::Version_1_1 to use BUILDARGS instead of around 'new'. 0.03 - Cleanup release... Some method name refactoring and better docs 0.02 - Various doc improvements - Marshal::HTTP can now make call->request conversion 0.01 - Initial release JSON-RPC-Common-0.11/dist.ini0000644002053500205350000000110312304200774015622 0ustar dmcbridedmcbridename = JSON-RPC-Common author = Yuval Kogman license = Perl_5 copyright_holder = Yuval Kogman and others [@Git] tag_format = JSON-RPC-Common-%v [Git::NextVersion] version_regexp = ^JSON-RPC-Common-(.+)$ [@Basic] [PkgVersion] [PodWeaver] [PodSyntaxTests] [ModuleBuild] [DualBuilders] [MetaJSON] [NextRelease] format = %-7v %{yyy-MM-dd}d [AutoPrereqs] skip = CGI::Expand [Prereqs] JSON = 2.11 Moose = 0.48 namespace::clean = 0.20 [Prereqs / TestRequires] Test::Exception = 0 [GithubMeta] [ContributorsFromGit] JSON-RPC-Common-0.11/META.json0000644002053500205350000000430612304200774015607 0ustar dmcbridedmcbride{ "abstract" : "Transport agnostic JSON RPC helper objects", "author" : [ "Yuval Kogman " ], "dynamic_config" : 0, "generated_by" : "Dist::Zilla version 5.012, CPAN::Meta::Converter version 2.133380", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : "2" }, "name" : "JSON-RPC-Common", "prereqs" : { "build" : { "requires" : { "Module::Build" : "0.3601" } }, "configure" : { "requires" : { "Module::Build" : "0.3601" } }, "develop" : { "requires" : { "Test::Pod" : "1.41" } }, "runtime" : { "requires" : { "Carp" : "0", "Class::Load" : "0", "HTTP::Response" : "0", "JSON" : "2.11", "MIME::Base64" : "0", "MRO::Compat" : "0", "Moose" : "0.48", "Moose::Role" : "0", "MooseX::Types" : "0", "MooseX::Types::Moose" : "0", "Try::Tiny" : "0", "URI::QueryParam" : "0", "namespace::clean" : "0.20", "strict" : "0", "warnings" : "0" } }, "test" : { "requires" : { "Data::Dumper" : "0", "Encode" : "0", "HTTP::Request" : "0", "Test::Exception" : "0", "Test::More" : "0", "utf8" : "0" } } }, "release_status" : "stable", "resources" : { "homepage" : "https://github.com/dmcbride/json-rpc-common", "repository" : { "type" : "git", "url" : "https://github.com/dmcbride/json-rpc-common.git", "web" : "https://github.com/dmcbride/json-rpc-common" } }, "version" : "0.11", "x_contributors" : [ "Darin McBride ", "Jesse Luehrs ", "Kazuhiro Osawa ", "Makamaka ", "Stevan Little ", "Stevan Little ", "Tokuhiro Matsuno " ] } JSON-RPC-Common-0.11/Build.PL0000644002053500205350000000314512304200774015462 0ustar dmcbridedmcbride # This file was automatically generated by Dist::Zilla::Plugin::ModuleBuild v5.012. use strict; use warnings; use Module::Build 0.3601; my %module_build_args = ( "build_requires" => { "Module::Build" => "0.3601" }, "configure_requires" => { "Module::Build" => "0.3601" }, "dist_abstract" => "Transport agnostic JSON RPC helper objects", "dist_author" => [ "Yuval Kogman " ], "dist_name" => "JSON-RPC-Common", "dist_version" => "0.11", "license" => "perl", "module_name" => "JSON::RPC::Common", "recommends" => {}, "recursive_test_files" => 1, "requires" => { "Carp" => 0, "Class::Load" => 0, "HTTP::Response" => 0, "JSON" => "2.11", "MIME::Base64" => 0, "MRO::Compat" => 0, "Moose" => "0.48", "Moose::Role" => 0, "MooseX::Types" => 0, "MooseX::Types::Moose" => 0, "Try::Tiny" => 0, "URI::QueryParam" => 0, "namespace::clean" => "0.20", "strict" => 0, "warnings" => 0 }, "script_files" => [], "test_requires" => { "Data::Dumper" => 0, "Encode" => 0, "HTTP::Request" => 0, "Test::Exception" => 0, "Test::More" => 0, "utf8" => 0 } ); my %fallback_build_requires = ( "Data::Dumper" => 0, "Encode" => 0, "HTTP::Request" => 0, "Module::Build" => "0.3601", "Test::Exception" => 0, "Test::More" => 0, "utf8" => 0 ); unless ( eval { Module::Build->VERSION(0.4004) } ) { delete $module_build_args{test_requires}; $module_build_args{build_requires} = \%fallback_build_requires; } my $build = Module::Build->new(%module_build_args); $build->create_build_script; JSON-RPC-Common-0.11/META.yml0000644002053500205350000000241112304200774015432 0ustar dmcbridedmcbride--- abstract: 'Transport agnostic JSON RPC helper objects' author: - 'Yuval Kogman ' build_requires: Data::Dumper: '0' Encode: '0' HTTP::Request: '0' Module::Build: '0.3601' Test::Exception: '0' Test::More: '0' utf8: '0' configure_requires: Module::Build: '0.3601' dynamic_config: 0 generated_by: 'Dist::Zilla version 5.012, CPAN::Meta::Converter version 2.133380' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: '1.4' name: JSON-RPC-Common requires: Carp: '0' Class::Load: '0' HTTP::Response: '0' JSON: '2.11' MIME::Base64: '0' MRO::Compat: '0' Moose: '0.48' Moose::Role: '0' MooseX::Types: '0' MooseX::Types::Moose: '0' Try::Tiny: '0' URI::QueryParam: '0' namespace::clean: '0.20' strict: '0' warnings: '0' resources: homepage: https://github.com/dmcbride/json-rpc-common repository: https://github.com/dmcbride/json-rpc-common.git version: '0.11' x_contributors: - 'Darin McBride ' - 'Jesse Luehrs ' - 'Kazuhiro Osawa ' - 'Makamaka ' - 'Stevan Little ' - 'Stevan Little ' - 'Tokuhiro Matsuno ' JSON-RPC-Common-0.11/Makefile.PL0000644002053500205350000000374712304200774016150 0ustar dmcbridedmcbride # This file was automatically generated by Dist::Zilla::Plugin::MakeMaker v5.012. use strict; use warnings; use ExtUtils::MakeMaker 6.30; my %WriteMakefileArgs = ( "ABSTRACT" => "Transport agnostic JSON RPC helper objects", "AUTHOR" => "Yuval Kogman ", "BUILD_REQUIRES" => { "Module::Build" => "0.3601" }, "CONFIGURE_REQUIRES" => { "Module::Build" => "0.3601" }, "DISTNAME" => "JSON-RPC-Common", "EXE_FILES" => [], "LICENSE" => "perl", "NAME" => "JSON::RPC::Common", "PREREQ_PM" => { "Carp" => 0, "Class::Load" => 0, "HTTP::Response" => 0, "JSON" => "2.11", "MIME::Base64" => 0, "MRO::Compat" => 0, "Moose" => "0.48", "Moose::Role" => 0, "MooseX::Types" => 0, "MooseX::Types::Moose" => 0, "Try::Tiny" => 0, "URI::QueryParam" => 0, "namespace::clean" => "0.20", "strict" => 0, "warnings" => 0 }, "TEST_REQUIRES" => { "Data::Dumper" => 0, "Encode" => 0, "HTTP::Request" => 0, "Test::Exception" => 0, "Test::More" => 0, "utf8" => 0 }, "VERSION" => "0.11", "test" => { "TESTS" => "t/*.t" } ); my %FallbackPrereqs = ( "Carp" => 0, "Class::Load" => 0, "Data::Dumper" => 0, "Encode" => 0, "HTTP::Request" => 0, "HTTP::Response" => 0, "JSON" => "2.11", "MIME::Base64" => 0, "MRO::Compat" => 0, "Module::Build" => "0.3601", "Moose" => "0.48", "Moose::Role" => 0, "MooseX::Types" => 0, "MooseX::Types::Moose" => 0, "Test::Exception" => 0, "Test::More" => 0, "Try::Tiny" => 0, "URI::QueryParam" => 0, "namespace::clean" => "0.20", "strict" => 0, "utf8" => 0, "warnings" => 0 ); unless ( eval { ExtUtils::MakeMaker->VERSION(6.63_03) } ) { delete $WriteMakefileArgs{TEST_REQUIRES}; delete $WriteMakefileArgs{BUILD_REQUIRES}; $WriteMakefileArgs{PREREQ_PM} = \%FallbackPrereqs; } delete $WriteMakefileArgs{CONFIGURE_REQUIRES} unless eval { ExtUtils::MakeMaker->VERSION(6.52) }; WriteMakefile(%WriteMakefileArgs);