The MSGPACK-RPC protocol¶
Example¶
The following example shows how to use the
MSGPACKRPCProtocol
class in a custom
application, without using any other components:
Server¶
from tinyrpc.protocols.msgpackrpc import MSGPACKRPCProtocol
from tinyrpc import BadRequestError, RPCRequest
rpc = MSGPACKRPCProtocol()
# the code below is valid for all protocols, not just MSGPACKRPCProtocol,
# as long as you don't need to handle batch RPC requests:
def handle_incoming_message(self, data):
try:
request = rpc.parse_request(data)
except BadRequestError as e:
# request was invalid, directly create response
response = e.error_respond(e)
else:
# we got a valid request
# the handle_request function is user-defined
# and returns some form of response
response = handle_request(request)
# now send the response to the client
if response != None:
send_to_client(response.serialize())
def handle_request(request):
try:
# do magic with method, args, kwargs...
return request.respond(result)
except Exception as e:
# for example, a method wasn't found
return request.error_respond(e)
Client¶
from tinyrpc.protocols.msgpackrpc import MSGPACKRPCProtocol
rpc = MSGPACKRPCProtocol()
# again, code below is protocol-independent
# assuming you want to call method(*args, **kwargs)
request = rpc.create_request(method, args, kwargs)
reply = send_to_server_and_get_reply(request)
response = rpc.parse_reply(reply)
if hasattr(response, 'error'):
# error handling...
else:
# the return value is found in response.result
do_something_with(response.result)
Finally, one-way requests are requests where the client does not expect an answer:
request = rpc.create_request(method, args, kwargs, one_way=True)
send_to_server(request)
# done
Protocol implementation¶
API Reference¶
-
class
tinyrpc.protocols.msgpackrpc.
MSGPACKRPCProtocol
(id_generator: Optional[Generator[object, None, None], None] = None, *args, **kwargs)¶ Bases:
tinyrpc.protocols.RPCProtocol
MSGPACKRPC protocol implementation.
-
request_factory
() → tinyrpc.protocols.msgpackrpc.MSGPACKRPCRequest¶ Factory for request objects.
Allows derived classes to use requests derived from
MSGPACKRPCRequest
.Return type: MSGPACKRPCRequest
-
create_request
(method: str, args: List[Any] = None, kwargs: Dict[str, Any] = None, one_way: bool = False) → tinyrpc.protocols.msgpackrpc.MSGPACKRPCRequest¶ Creates a new
MSGPACKRPCRequest
object.Called by the client when constructing a request. MSGPACK-RPC allows only the
args
argument to be set; keyword arguments are not supported.Parameters: - method (str) – The method name to invoke.
- args (list) – The positional arguments to call the method with.
- kwargs (dict) – The keyword arguments to call the method with; must
be
None
as the protocol does not support keyword arguments. - one_way (bool) – The request is an update, i.e. it does not expect a reply.
Returns: A new request instance
Return type: Raises: InvalidRequestError – when
kwargs
is defined.
-
parse_reply
(data: bytes) → Union[tinyrpc.protocols.msgpackrpc.MSGPACKRPCSuccessResponse, tinyrpc.protocols.msgpackrpc.MSGPACKRPCErrorResponse]¶ De-serializes and validates a response.
Called by the client to reconstruct the serialized
MSGPACKRPCResponse
.Parameters: data (bytes) – The data stream received by the transport layer containing the serialized response. Returns: A reconstructed response. Return type: MSGPACKRPCSuccessResponse
orMSGPACKRPCErrorResponse
Raises: InvalidReplyError – if the response is not valid MSGPACK or does not conform to the standard.
-
parse_request
(data: bytes) → tinyrpc.protocols.msgpackrpc.MSGPACKRPCRequest¶ De-serializes and validates a request.
Called by the server to reconstruct the serialized
MSGPACKRPCRequest
.Parameters: data (bytes) – The data stream received by the transport layer containing the serialized request.
Returns: A reconstructed request.
Return type: Raises: - MSGPACKRPCParseError – if the
data
cannot be parsed as valid MSGPACK. - MSGPACKRPCInvalidRequestError – if the request does not comply with the standard.
- MSGPACKRPCParseError – if the
-
raise_error
(error: Union[MSGPACKRPCErrorResponse, Dict[str, Any]]) → tinyrpc.protocols.msgpackrpc.MSGPACKRPCError¶ Recreates the exception.
Creates a
MSGPACKRPCError
instance and raises it.This allows the error code and the message of the original exception to propagate into the client code.
The
raises_error
flag controls if the exception object is raised or returned.Returns: the exception object if it is not allowed to raise it. Raises: MSGPACKRPCError – when the exception can be raised. The exception object will contain message
andcode
.
-
-
class
tinyrpc.protocols.msgpackrpc.
MSGPACKRPCRequest
¶ Bases:
tinyrpc.protocols.RPCRequest
Defines a MSGPACK-RPC request.
-
one_way
= None¶ Request or Notification.
Type: bool This flag indicates if the client expects to receive a reply (request:
one_way = False
) or not (notification:one_way = True
).Note that it is possible for the server to return an error response. For example if the request becomes unreadable and the server is not able to determine that it is in fact a notification an error should be returned. However, once the server had verified that the request is a notification no reply (not even an error) should be returned.
-
unique_id
= None¶ Correlation ID used to match request and response.
Type: int Generated by the client, the server copies it from request to corresponding response.
-
method
= None¶ The name of the RPC function to be called.
Type: str The
method
attribute uses the name of the function as it is known by the public. TheRPCDispatcher
allows the use of public aliases in the@public
decorators. These are the names used in themethod
attribute.
-
args
= None¶ The positional arguments of the method call.
Type: list The contents of this list are the positional parameters for the
method
called. It is eventually called asmethod(*args)
.
-
error_respond
(error: Union[Exception, str]) → Optional[tinyrpc.protocols.msgpackrpc.MSGPACKRPCErrorResponse, None]¶ Create an error response to this request.
When processing the request produces an error condition this method can be used to create the error response object.
Parameters: error (Exception or str) – Specifies what error occurred. Returns: An error response object that can be serialized and sent to the client. Return type: ;py:class:MSGPACKRPCErrorResponse
-
respond
(result: Any) → Optional[tinyrpc.protocols.msgpackrpc.MSGPACKRPCSuccessResponse, None]¶ Create a response to this request.
When processing the request completed successfully this method can be used to create a response object.
Parameters: result (Anything that can be encoded by MSGPACK.) – The result of the invoked method. Returns: A response object that can be serialized and sent to the client. Return type: MSGPACKRPCSuccessResponse
-
-
class
tinyrpc.protocols.msgpackrpc.
MSGPACKRPCSuccessResponse
¶
-
class
tinyrpc.protocols.msgpackrpc.
MSGPACKRPCErrorResponse
¶
Errors and error handling¶
API Reference¶
-
class
tinyrpc.protocols.msgpackrpc.
MSGPACKRPCParseError
(*args, **kwargs)¶ Bases:
tinyrpc.protocols.msgpackrpc.FixedErrorMessageMixin
,tinyrpc.exc.InvalidRequestError
-
class
tinyrpc.protocols.msgpackrpc.
MSGPACKRPCInvalidRequestError
(*args, **kwargs)¶ Bases:
tinyrpc.protocols.msgpackrpc.FixedErrorMessageMixin
,tinyrpc.exc.InvalidRequestError
-
class
tinyrpc.protocols.msgpackrpc.
MSGPACKRPCMethodNotFoundError
(*args, **kwargs)¶ Bases:
tinyrpc.protocols.msgpackrpc.FixedErrorMessageMixin
,tinyrpc.exc.MethodNotFoundError
-
class
tinyrpc.protocols.msgpackrpc.
MSGPACKRPCInvalidParamsError
(*args, **kwargs)¶ Bases:
tinyrpc.protocols.msgpackrpc.FixedErrorMessageMixin
,tinyrpc.exc.InvalidRequestError
-
class
tinyrpc.protocols.msgpackrpc.
MSGPACKRPCInternalError
(*args, **kwargs)¶ Bases:
tinyrpc.protocols.msgpackrpc.FixedErrorMessageMixin
,tinyrpc.exc.InvalidRequestError
-
class
tinyrpc.protocols.msgpackrpc.
MSGPACKRPCServerError
(*args, **kwargs)¶ Bases:
tinyrpc.protocols.msgpackrpc.FixedErrorMessageMixin
,tinyrpc.exc.InvalidRequestError
-
class
tinyrpc.protocols.msgpackrpc.
MSGPACKRPCError
(error: Union[MSGPACKRPCErrorResponse, Tuple[int, str]])¶ Bases:
tinyrpc.protocols.msgpackrpc.FixedErrorMessageMixin
,tinyrpc.exc.RPCError
Reconstructs (to some extend) the server-side exception.
The client creates this exception by providing it with the
error
attribute of the MSGPACK error response object returned by the server.Parameters: error – This tuple contains the error specification: the numeric error code and the error description.
Adding custom exceptions¶
Note
Unlike JSON-RPC, the MSGPACK-RPC specification does not specify how
the error messages should look like; the protocol allows any arbitrary
MSGPACK object as an error object. For sake of compatibility with JSON-RPC,
this implementation uses MSGPACK lists of length 2 (consisting of a numeric
error code and an error description) to represent errors in the serialized
representation. These are transparently decoded into
MSGPACKRPCError
instances as
needed. The error codes for parsing errors, invalid requests, unknown RPC
methods and so on match those from the JSON-RPC specification.
To add custom errors you need to combine an Exception
subclass
with the FixedErrorMessageMixin
class
to create your exception object which you can raise.
So a version of the reverse string example that dislikes palindromes could look like:
from tinyrpc.protocols.msgpackrpc import FixedErrorMessageMixin, MSGPACKRPCProtocol
from tinyrpc.dispatch import RPCDispatcher
dispatcher = RPCDispatcher()
class PalindromeError(FixedErrorMessageMixin, Exception):
msgpackrpc_error_code = 99
message = "Ah, that's cheating!"
@dispatcher.public
def reverse_string(s):
r = s[::-1]
if r == s:
raise PalindromeError()
return r