Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Exceptions are in X::JSON::RPC scope.

http://perl6advent.wordpress.com/2012/12/12/exceptions/

explains:

"In Perl 6, exceptions should inherit from the type Exception, and by
convention they go into the X:: namespace."
  • Loading branch information...
commit 5dd124909e33015222e1e69a6c97ed532b8330e0 1 parent 0ce7b2b
@bbkr authored
View
2  META.info
@@ -11,5 +11,5 @@
"name": "JSON::RPC",
"repo-type": "git",
"source-url": "git://github.com/bbkr/jsonrpc.git",
- "version": "0.13.0"
+ "version": "0.14.0"
}
View
28 README.md
@@ -187,14 +187,14 @@ For example code `204 No Content` should be used in HTTP transport.
### How to implement Error handling?
-Errors defined in 2.0 spec are represented by `JSON::RPC::Error` exceptions:
+Errors defined in 2.0 spec are represented by `X::JSON::RPC` exceptions:
-* `JSON::RPC::ParseError` - Invalid JSON was received by the server.
-* `JSON::RPC::InvalidRequest` - The structure sent by client is not a valid Request object.
-* `JSON::RPC::MethodNotFound` - The method does not exist in server handler application.
-* `JSON::RPC::InvalidParams` - Invalid method parameters, no handler candidates with matching signature found.
-* `JSON::RPC::InternalError` - Remote method died.
-* `JSON::RPC::ProtocolError` - Other deviation from specification.
+* `X::JSON::RPC::ParseError` - Invalid JSON was received by the server.
+* `X::JSON::RPC::InvalidRequest` - The structure sent by client is not a valid Request object.
+* `X::JSON::RPC::MethodNotFound` - The method does not exist in server handler application.
+* `X::JSON::RPC::InvalidParams` - Invalid method parameters, no handler candidates with matching signature found.
+* `X::JSON::RPC::InternalError` - Remote method died.
+* `X::JSON::RPC::ProtocolError` - Other deviation from specification.
Every exception has numeric `code` attribute that indicates the error type that occurred, text `message` attribute that provides a short description of the error and optional `data` attribute that contains additional information about the error.
@@ -204,7 +204,7 @@ Every exception has numeric `code` attribute that indicates the error type that
try {
$c.hello( 'John Doe' );
CATCH {
- when JSON::RPC::MethodNotFound {
+ when X::JSON::RPC::MethodNotFound {
say 'Server is rude';
}
default {
@@ -228,20 +228,20 @@ Every exception has numeric `code` attribute that indicates the error type that
Client will receive `message` attribute "Internal error." with explanation "Cannot divide by 0" as `data` attribute.
-* Throw `JSON::RPC::Error` exception.
+* Throw `X::JSON::RPC` exception.
```perl
class My::App {
method treasure {
- JSON::RPC::Error.new( code => -1, message => 'Access denied.', data => 'Thou shall not pass!' ).throw;
+ X::JSON::RPC.new( code => -1, message => 'Access denied.', data => 'Thou shall not pass!' ).throw;
}
}
```
-Exception `JSON::RPC::Error` is composable so you can easily define your own errors.
+Exception `X::JSON::RPC` is composable so you can easily define your own errors.
```perl
- class My::Error does JSON::RPC::Error {
+ class My::Error does X::JSON::RPC {
method new {
self.bless( *, code => -1, message => 'Access denied.', data => 'Thou shall not pass!' );
}
@@ -288,7 +288,7 @@ Method `'rpc.batch'( )` puts client in batch context while method `'rpc.flush'(
try {
$response.say;
CATCH {
- when JSON::RPC::Error {
+ when X::JSON::RPC {
say 'Oops! ', .message;
}
}
@@ -306,7 +306,7 @@ Important things to remember:
* Client will sort responses to match order in which methods were stacked.
* Notifications do not have corresponding response.
* Batch containing only Notifications will return Nil on flush.
-* Attempt to flush empty Batch will result in `JSON::RPC::InvalidRequest` exception.
+* Attempt to flush empty Batch will result in `X::JSON::RPC::InvalidRequest` exception.
* Individual exceptions are returned as Failures, thrown when called in sink context.
You can save client context to avoid typing.
View
36 lib/JSON/RPC/Client.pm
@@ -1,7 +1,7 @@
use URI;
use LWP::Simple;
use JSON::Tiny;
-use JSON::RPC::Error;
+use X::JSON::RPC;
class JSON::RPC::Client;
@@ -26,7 +26,7 @@ INIT {
# so dispatch has to be done manually depending on nature of passed params
return method ( *@positional, *%named ) {
if @positional and %named {
- JSON::RPC::ProtocolError.new(
+ X::JSON::RPC::ProtocolError.new(
message => 'Cannot use positional and named params at the same time.'
).throw;
}
@@ -127,11 +127,11 @@ method !handler( Str :$method!, :$params ) {
my $out = self!validate_response( $response );
# failed procedure call, throw exception.
- $out.throw if $out ~~ JSON::RPC::Error;
+ $out.throw if $out ~~ X::JSON::RPC;
# SPEC: This member is REQUIRED.
# It MUST be the same as the value of the id member in the Request Object.
- JSON::RPC::ProtocolError.new(
+ X::JSON::RPC::ProtocolError.new(
message => 'Request id is different than response id.',
data => { 'request' => %request, 'response' => $response }
).throw unless %request{'id'} eqv $response{'id'};
@@ -210,7 +210,7 @@ method ::('rpc.flush') {
if $subposition;
# extract relevant part of Response
- $responses[ $position ] = ( $response{'out'} ~~ JSON::RPC::Error )
+ $responses[ $position ] = ( $response{'out'} ~~ X::JSON::RPC )
?? Failure.new( $response{'out'} )
!! $response{'out'};
@@ -224,7 +224,7 @@ method ::('rpc.flush') {
# if Response was not found by id member it must be Invalid Request error
for $responses[ $position .. * ].kv -> $subposition, $response {
- next unless $response{'out'} ~~ JSON::RPC::InvalidRequest;
+ next unless $response{'out'} ~~ X::JSON::RPC::InvalidRequest;
# swap Responses at position being checked and desired position if not already in place
$responses[ $position, $position + $subposition ] = $responses[ $position + $subposition, $position ]
@@ -237,13 +237,13 @@ method ::('rpc.flush') {
last;
}
- JSON::RPC::ProtocolError.new(
+ X::JSON::RPC::ProtocolError.new(
message => 'Cannot match context between Requests and Responses in Batch.',
data => { 'requests' => @!stack, 'responses' => $responses }
).throw unless $found;
LAST {
- JSON::RPC::ProtocolError.new(
+ X::JSON::RPC::ProtocolError.new(
message => 'Amount of Responses in Batch higher than expected',
data => { 'requests' => @!stack, 'responses' => $responses }
).throw if $position != $responses.elems - 1;
@@ -262,8 +262,8 @@ method !parse_json ( Str $body ) {
try { $parsed = from-json( $body ); };
- JSON::RPC::ProtocolError.new( data => ~$! ).throw if defined $!;
- JSON::RPC::ProtocolError.new.throw unless $parsed ~~ Array|Hash;
+ X::JSON::RPC::ProtocolError.new( data => ~$! ).throw if defined $!;
+ X::JSON::RPC::ProtocolError.new.throw unless $parsed ~~ Array|Hash;
return $parsed;
}
@@ -300,7 +300,7 @@ method !validate_response ( $response ) {
return self!bind_error( $response{'error'} );
}
default {
- JSON::RPC::ProtocolError.new(
+ X::JSON::RPC::ProtocolError.new(
message => 'Invalid Response.',
data => $response
).throw;
@@ -327,29 +327,29 @@ method !bind_error ( $error ) {
# This may be omitted.
subset ErrorMemberData of Any;
- JSON::RPC::ProtocolError.new(
+ X::JSON::RPC::ProtocolError.new(
message => 'Invalid Error.',
data => $error
).throw unless $error ~~ :( ErrorMemberCode :$code!, ErrorMemberMessage :$message!, ErrorMemberData :$data? );
given $error{'code'} {
when -32700 {
- return JSON::RPC::ParseError.new( |$error );
+ return X::JSON::RPC::ParseError.new( |$error );
}
when -32600 {
- return JSON::RPC::InvalidRequest.new( |$error );
+ return X::JSON::RPC::InvalidRequest.new( |$error );
}
when -32601 {
- return JSON::RPC::MethodNotFound.new( |$error );
+ return X::JSON::RPC::MethodNotFound.new( |$error );
}
when -32602 {
- return JSON::RPC::InvalidParams.new( |$error );
+ return X::JSON::RPC::InvalidParams.new( |$error );
}
when -32603 {
- return JSON::RPC::InternalError.new( |$error );
+ return X::JSON::RPC::InternalError.new( |$error );
}
default {
- return JSON::RPC::Error.new( |$error );
+ return X::JSON::RPC.new( |$error );
}
}
}
View
24 lib/JSON/RPC/Server.pm
@@ -1,5 +1,5 @@
use JSON::Tiny;
-use JSON::RPC::Error;
+use X::JSON::RPC;
use HTTP::Easy::PSGI;
class JSON::RPC::Server;
@@ -58,7 +58,7 @@ method handler ( Str :$json! ) {
# SPEC: To send several Request objects at the same time,
# the Client MAY send an Array filled with Request objects.
# (empty Array is not valid request)
- JSON::RPC::InvalidRequest.new.throw unless $parsed.elems;
+ X::JSON::RPC::InvalidRequest.new.throw unless $parsed.elems;
@requests = $parsed.list;
}
else {
@@ -103,7 +103,7 @@ method handler ( Str :$json! ) {
%response{'result'} = $result;
CATCH {
- when JSON::RPC::InvalidRequest {
+ when X::JSON::RPC::InvalidRequest {
%response = %template;
@@ -114,7 +114,7 @@ method handler ( Str :$json! ) {
# If there was an error in detecting the id in the Request object, it MUST be Null.
%response{'id'} = Any;
}
- when JSON::RPC::Error {
+ when X::JSON::RPC {
# SPEC: Notifications are not confirmable by definition,
# since they do not have a Response object to be returned.
@@ -139,7 +139,7 @@ method handler ( Str :$json! ) {
# SPEC: If the batch rpc call itself fails to be recognized as an valid JSON
# or as an Array with at least one value,
# the response from the Server MUST be a single Response object.
- when JSON::RPC::ParseError|JSON::RPC::InvalidRequest {
+ when X::JSON::RPC::ParseError|X::JSON::RPC::InvalidRequest {
# SPEC: Response object
$out = %template;
@@ -163,8 +163,8 @@ method !parse_json ( Str $body ) {
try { $parsed = from-json( $body ); };
- JSON::RPC::ParseError.new( data => ~$! ).throw if defined $!;
- JSON::RPC::ParseError.new.throw unless $parsed ~~ Array|Hash;
+ X::JSON::RPC::ParseError.new( data => ~$! ).throw if defined $!;
+ X::JSON::RPC::ParseError.new.throw unless $parsed ~~ Array|Hash;
return $parsed;
}
@@ -205,7 +205,7 @@ method !validate_request ( $request ) {
$mode = 'Notification';
}
default {
- JSON::RPC::InvalidRequest.new.throw;
+ X::JSON::RPC::InvalidRequest.new.throw;
}
}
@@ -217,7 +217,7 @@ method !search_method ( Str $name ) {
# locate public method in application
my $method = $.application.^find_method( $name );
- JSON::RPC::MethodNotFound.new.throw unless $method;
+ X::JSON::RPC::MethodNotFound.new.throw unless $method;
return $method;
}
@@ -227,7 +227,7 @@ method !validate_params ( Routine $method, |params ) {
# find all method candidates that recognize passed params
my @candidates = $method.cando( params );
- JSON::RPC::InvalidParams.new.throw unless @candidates;
+ X::JSON::RPC::InvalidParams.new.throw unless @candidates;
# many mathches are not an error
# first candidate is taken
@@ -244,8 +244,8 @@ method !call ( Method $candidate, |params ) {
CATCH {
# wrap unhandled error type as internal error
- when not $_ ~~ JSON::RPC::Error {
- JSON::RPC::InternalError.new( data => .Str ).throw;
+ when not $_ ~~ X::JSON::RPC {
+ X::JSON::RPC::InternalError.new( data => .Str ).throw;
}
}
};
View
14 lib/JSON/RPC/Error.pm → lib/X/JSON/RPC.pm
@@ -1,7 +1,7 @@
# JSON-PRC 2.0 spec defines Error Object in chapter 5.1
# derived from http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php
-role JSON::RPC::Error is Exception {
+role X::JSON::RPC is Exception {
# SPEC: When a rpc call encounters an error,
# the Response Object MUST contain the error member
@@ -47,7 +47,7 @@ role JSON::RPC::Error is Exception {
# invalid JSON was received by the server.
# an error occurred on the server while parsing the JSON text.
-class JSON::RPC::ParseError does JSON::RPC::Error {
+class X::JSON::RPC::ParseError does X::JSON::RPC {
method new ( :$data ) {
self.bless( *, code => -32700, message => 'Parse error.', data => $data );
@@ -56,7 +56,7 @@ class JSON::RPC::ParseError does JSON::RPC::Error {
}
# the JSON sent is not a valid Request object
-class JSON::RPC::InvalidRequest does JSON::RPC::Error {
+class X::JSON::RPC::InvalidRequest does X::JSON::RPC {
method new ( :$data ) {
self.bless( *, code => -32600, message => 'Invalid Request.', data => $data );
@@ -65,7 +65,7 @@ class JSON::RPC::InvalidRequest does JSON::RPC::Error {
}
# the method does not exist / is not available
-class JSON::RPC::MethodNotFound does JSON::RPC::Error {
+class X::JSON::RPC::MethodNotFound does X::JSON::RPC {
method new ( :$data ) {
self.bless( *, code => -32601, message => 'Method not found.', data => $data );
@@ -74,7 +74,7 @@ class JSON::RPC::MethodNotFound does JSON::RPC::Error {
}
# invalid method parameter(s)
-class JSON::RPC::InvalidParams does JSON::RPC::Error {
+class X::JSON::RPC::InvalidParams does X::JSON::RPC {
method new ( :$data ) {
self.bless( *, code => -32602, message => 'Invalid params.', data => $data );
@@ -83,7 +83,7 @@ class JSON::RPC::InvalidParams does JSON::RPC::Error {
}
# internal JSON-RPC error
-class JSON::RPC::InternalError does JSON::RPC::Error {
+class X::JSON::RPC::InternalError does X::JSON::RPC {
method new ( :$data ) {
self.bless( *, code => -32603, message => 'Internal error.', data => $data );
@@ -92,7 +92,7 @@ class JSON::RPC::InternalError does JSON::RPC::Error {
}
# protocol error
-class JSON::RPC::ProtocolError does JSON::RPC::Error {
+class X::JSON::RPC::ProtocolError does X::JSON::RPC {
method new ( :$message, :$data ) {
self.bless( *, code => -32000, message => $message // 'Protocol Error.', data => $data );
View
28 t/client.t
@@ -62,7 +62,7 @@ spec(
ids => [ '1' ]
);
try { $rpc.foobar( ) };
-isa_ok $!, JSON::RPC::MethodNotFound, $name;
+isa_ok $!, X::JSON::RPC::MethodNotFound, $name;
spec(
'rpc call with invalid JSON',
@@ -71,7 +71,7 @@ spec(
force => True
);
try { $rpc.dummy( ) };
-isa_ok $!, JSON::RPC::ParseError, $name;
+isa_ok $!, X::JSON::RPC::ParseError, $name;
spec(
'rpc call with invalid Request object',
@@ -80,7 +80,7 @@ spec(
force => True
);
try { $rpc.dummy( ) };
-isa_ok $!, JSON::RPC::InvalidRequest, $name;
+isa_ok $!, X::JSON::RPC::InvalidRequest, $name;
spec(
'rpc call Batch, invalid JSON',
@@ -95,7 +95,7 @@ try {
$rpc.'rpc.batch'( ).dummy( );
$rpc.'rpc.flush'( );
};
-isa_ok $!, JSON::RPC::ParseError, $name;
+isa_ok $!, X::JSON::RPC::ParseError, $name;
spec(
'rpc call with an empty Array',
@@ -103,7 +103,7 @@ spec(
'{"jsonrpc": "2.0", "error": {"code": -32600, "message": "Invalid Request."}, "id": null}'
);
try { $rpc.'rpc.flush'( ) };
-isa_ok $!, JSON::RPC::InvalidRequest, $name;
+isa_ok $!, X::JSON::RPC::InvalidRequest, $name;
spec(
'rpc call with an invalid Batch (but not empty)',
@@ -118,7 +118,7 @@ lives_ok {
@responses = $rpc.'rpc.flush'( );
}, $name;
try { ~@responses[ 0 ] };
-isa_ok $!, JSON::RPC::InvalidRequest, $name ~ ' validate';
+isa_ok $!, X::JSON::RPC::InvalidRequest, $name ~ ' validate';
spec(
'rpc call with invalid Batch',
@@ -137,11 +137,11 @@ lives_ok {
@responses = $rpc.'rpc.flush'( );
}, $name;
try { ~@responses[ 0 ] };
-isa_ok $!, JSON::RPC::InvalidRequest, $name ~ ' validate';
+isa_ok $!, X::JSON::RPC::InvalidRequest, $name ~ ' validate';
try { ~@responses[ 1 ] };
-isa_ok $!, JSON::RPC::InvalidRequest, $name ~ ' validate';
+isa_ok $!, X::JSON::RPC::InvalidRequest, $name ~ ' validate';
try { ~@responses[ 2 ] };
-isa_ok $!, JSON::RPC::InvalidRequest, $name ~ ' validate';
+isa_ok $!, X::JSON::RPC::InvalidRequest, $name ~ ' validate';
spec(
'rpc call Batch',
@@ -174,9 +174,9 @@ lives_ok {
is @responses[ 0 ], 7, $name ~ ' validate';
is @responses[ 1 ], 19, $name ~ ' validate';
try { ~@responses[ 2 ] };
-isa_ok $!, JSON::RPC::InvalidRequest, $name ~ ' validate';
+isa_ok $!, X::JSON::RPC::InvalidRequest, $name ~ ' validate';
try { ~@responses[ 3 ] };
-isa_ok $!, JSON::RPC::MethodNotFound, $name ~ ' validate';
+isa_ok $!, X::JSON::RPC::MethodNotFound, $name ~ ' validate';
is_deeply @responses[ 4 ], [ 'hello', 5 ], $name ~ ' validate';
spec(
@@ -209,7 +209,7 @@ lives_ok {
}, 'can initialize using URI object';
try { $rpc.ping( ) };
-isa_ok $!, JSON::RPC::ProtocolError, 'live test';
+isa_ok $!, X::JSON::RPC::ProtocolError, 'live test';
spec(
'params member omitted when no params passed',
@@ -283,10 +283,10 @@ try {
$rpc.'rpc.batch'( ).pong( );
$rpc.'rpc.flush'( )
};
-isa_ok $!, JSON::RPC::ProtocolError, $name ~ ' validate';
+isa_ok $!, X::JSON::RPC::ProtocolError, $name ~ ' validate';
try { $rpc.subtract( 23, minuend => 42 ) };
-isa_ok $!, JSON::RPC::ProtocolError, 'cannot use positional and named params at the same time';
+isa_ok $!, X::JSON::RPC::ProtocolError, 'cannot use positional and named params at the same time';
# mocked handlers for transport layer
View
2  t/server.t
@@ -6,7 +6,7 @@ use JSON::RPC::Server;
plan( 28 );
-class CustomError does JSON::RPC::Error {
+class CustomError does X::JSON::RPC {
method new {
self.bless( *, code => -1, message => 'GLaDOS is watching.', data => 'The cake was a lie.' );
}
Please sign in to comment.
Something went wrong with that request. Please try again.