The protocol layer¶
Any protocol is implemented by deriving from RPCProtocol
and implementing all of its members:
-
class
tinyrpc.
RPCProtocol
¶ Base class for all protocol implementations.
-
create_request
(method, args=None, kwargs=None, one_way=False)¶ Creates a new RPCRequest object.
It is up to the implementing protocol whether or not
args
,kwargs
, one of these, both at once or none of them are supported.Parameters: - method – The method name to invoke.
- args – The positional arguments to call the method with.
- kwargs – The keyword arguments to call the method with.
- one_way – The request is an update, i.e. it does not expect a reply.
Returns: A new
RPCRequest
instance.
-
parse_reply
(data)¶ Parses a reply and returns an
RPCResponse
instance.Returns: An instanced response.
-
parse_request
(data)¶ Parses a request given as a string and returns an
RPCRequest
instance.Returns: An instanced request.
-
These require implementations of the following classes as well:
-
class
tinyrpc.
RPCRequest
¶ -
error_respond
(error)¶ Creates an error response.
Create a response indicating that the request was parsed correctly, but an error has occured trying to fulfill it.
Parameters: error – An exception or a string describing the error. Returns: A response or None
to indicate that no error should be sent out.
-
respond
(result)¶ Create a response.
Call this to return the result of a successful method invocation.
This creates and returns an instance of a protocol-specific subclass of
RPCResponse
.Parameters: result – Passed on to new response instance. Returns: A response or None
to indicate this request does not expect a response.
-
serialize
()¶ Returns a serialization of the request.
Returns: A string to be passed on to a transport.
-
-
class
tinyrpc.
RPCResponse
¶ RPC call response class.
Base class for all deriving responses.
Has an attribute
result
containing the result of the RPC call, unless an error occured, in which case an attributeerror
will contain the error message.-
serialize
()¶ Returns a serialization of the response.
Returns: A reply to be passed on to a transport.
-
-
class
tinyrpc.
BadRequestError
¶ Base class for all errors that caused the processing of a request to abort before a request object could be instantiated.
-
error_respond
()¶ Create
RPCErrorResponse
to respond the error.Returns: A error responce instance or None
, if the protocol decides to drop the error silently.
-
Every protocol deals with multiple kinds of structures: data
arguments are
always byte strings, either messages or replies, that are sent via or received
from a transport.
There are two protocol-specific subclasses of
RPCRequest
and RPCResponse
, these
represent well-formed requests and responses.
Finally, if an error occurs during parsing of a request, a
BadRequestError
instance must be thrown. These need to be
subclassed for each protocol as well, since they generate error replies.
Batch protocols¶
Some protocols may support batch requests. In this case, they need to derive
from RPCBatchProtocol
.
Batch protocols differ in that their
parse_request()
method may return an instance of
RPCBatchRequest
. They also possess an addional method in
create_batch_request()
.
Handling a batch request is slightly different, while it supports
error_respond()
, to make actual responses,
create_batch_response()
needs to be used.
No assumptions are made whether or not it is okay for batch requests to be handled in parallel. This is up to the server/dispatch implementation, which must be chosen appropriately.
-
class
tinyrpc.
RPCBatchProtocol
¶ -
create_batch_request
(requests=None)¶ Create a new
tinyrpc.RPCBatchRequest
object.Parameters: requests – A list of requests.
-
-
class
tinyrpc.
RPCBatchRequest
¶ Multiple requests batched together.
A batch request is a subclass of
list
. Protocols that support multiple requests in a single message use this to group them together.Handling a batch requests is done in any order, responses must be gathered in a batch response and be in the same order as their respective requests.
Any item of a batch request is either a request or a subclass of
BadRequestError
, which indicates that there has been an error in parsing the request.-
create_batch_response
()¶ Creates a response suitable for responding to this request.
Returns: An RPCBatchResponse
orNone
, if no response is expected.
-
-
class
tinyrpc.
RPCBatchResponse
¶ Multiple response from a batch request. See
RPCBatchRequest
on how to handle.Items in a batch response need to be
RPCResponse
instances or None, meaning no reply should generated for the request.-
serialize
()¶ Returns a serialization of the batch response.
-
Supported protocols¶
Any supported protocol is used by instantiating its class and calling the
interface of RPCProtocol
. Note that constructors are not
part of the interface, any protocol may have specific arguments for its
instances.
Protocols usually live in their own module because they may need to import
optional modules that needn’t be a dependency for all of tinyrpc
.
Example¶
The following example shows how to use the
JSONRPCProtocol
class in a custom
application, without using any other components:
Server¶
from tinyrpc.protocols.jsonrpc import JSONRPCProtocol
from tinyrpc import BadRequestError, RPCBatchRequest
rpc = JSONRPCProtocol()
# the code below is valid for all protocols, not just JSONRPC:
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
if hasattr(request, create_batch_response):
response = request.create_batch_response(
handle_request(req) for req in request
)
else:
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.jsonrpc import JSONRPCProtocol
rpc = JSONRPCProtocol()
# 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)
Another example, this time using batch requests:
# or using batch requests:
requests = rpc.create_batch_request([
rpc.create_request(method_1, args_1, kwargs_1)
rpc.create_request(method_2, args_2, kwargs_2)
# ...
])
reply = send_to_server_and_get_reply(request)
responses = rpc.parse_reply(reply)
for responses in response:
if hasattr(reponse, 'error'):
# ...
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
JSON-RPC¶
-
class
tinyrpc.protocols.jsonrpc.
JSONRPCProtocol
(*args, **kwargs)¶ JSONRPC protocol implementation.
Currently, only version 2.0 is supported.
-
create_batch_request
(requests=None)¶ Create a new
tinyrpc.RPCBatchRequest
object.Parameters: requests – A list of requests.
-
create_request
(method, args=None, kwargs=None, one_way=False)¶ Creates a new RPCRequest object.
It is up to the implementing protocol whether or not
args
,kwargs
, one of these, both at once or none of them are supported.Parameters: - method – The method name to invoke.
- args – The positional arguments to call the method with.
- kwargs – The keyword arguments to call the method with.
- one_way – The request is an update, i.e. it does not expect a reply.
Returns: A new
RPCRequest
instance.
-
parse_reply
(data)¶ Parses a reply and returns an
RPCResponse
instance.Returns: An instanced response.
-
parse_request
(data)¶ Parses a request given as a string and returns an
RPCRequest
instance.Returns: An instanced request.
-