.. _jsonrpc: ======== JSON-RPC ======== :mod:`pyramid_rpc` supports `JSON-RPC 2.0 Specification `_ . .. code-block:: python from pyramid.config import Configurator from pyramic_rpc import jsonrpc_method @jsonrpc_method(endpoint='api') def say_hello(request, name): return 'hello, %s!' % name def main(global_conf, **settings): config = Configurator(settings=settings) config.include('pyramid_rpc.jsonrpc') config.add_jsonrpc_endpoint('api', '/api') config.scan(__name__) return config.make_wsgi_app() if __name__ == '__main__': from paste.httpserver import serve app = main({}) serve(app, 'localhost', 8080) Setup ===== Use the ``includeme`` via :meth:`pyramid.config.Configurator.include`: .. code-block:: python config.include('pyramid_rpc.jsonrpc') Once activated, the following happens: #. The :meth:`pyramid_rpc.jsonrpc.add_jsonrpc_endpoint` directive is added to the ``config`` instance. #. The :meth:`pyramid_rpc.jsonrpc.add_jsonrpc_method` directive is added to the ``config`` instance. #. An exception view is registered for :class:`pyramid_rpc.jsonrpc.JsonRpcError` exceptions. Usage ===== After including the ``pyramid_rpc.jsonrpc`` package in your project, you can add an :term:`endpoint` for handling incoming requests. After that, attach several methods to the endpoint to handle specific functions within your api. Adding a JSON-RPC Endpoint -------------------------- An :term:`endpoint` is added via the :func:`~pyramid_rpc.jsonrpc.add_jsonrpc_endpoint` directive on the ``config`` instance. Example: .. code-block:: python config = Configurator() config.include('pyramid_rpc.jsonrpc') config.add_jsonrpc_endpoint('api', '/api/jsonrpc') It is possible to add multiple endpoints as well as pass extra arguments to :func:`~pyramid_rpc.jsonrpc.add_jsonrpc_endpoint` to handle traversal, which can assist in adding security to your RPC API. Exposing JSON-RPC Methods ------------------------- Methods on your API are exposed by attaching views to an :term:`endpoint`. Methods may be attached via the :func:`~pyramid_rpc.jsonrpc.add_jsonrpc_method` which is a thin wrapper around :meth:`pyramid.config.Configurator.add_view` method. Example: .. code-block:: python def say_hello(request, name): return 'Hello, ' + name config.add_jsonrpc_method(say_hello, endpoint='api', method='say_hello') If you prefer, you can use the :func:`~pyramid_rpc.jsonrpc.jsonrpc_method` view decorator to declare your methods closer to your actual code. Remember when using this lazy configuration technique, it's always necessary to call :meth:`pyramid.config.Configurator.scan` from within your setup code. .. code-block:: python from pyramid_rpc.jsonrpc import jsonrpc_method @jsonrpc_method(endpoint='api') def say_hello(request, name): return 'Hello, ' + name config.scan() To set the RPC method to something other than the name of the view, specify the ``method`` parameter: .. code-block:: python from pyramid_rpc.jsonrpc import jsonrpc_method @jsonrpc_method(method='say_hello', endpoint='api') def say_hello_view(request, name): return 'Hello, ' + name config.scan() Because methods are a thin layer around Pyramid's views, it is possible to add extra view predicates to the method, as well as ``permission`` requirements. .. _jsonrpc_custom_renderers: Custom Renderers ---------------- By default, responses are rendered using the Python standard library's :func:`json.dumps`. This can be changed the same way any renderer is changed in Pyramid. See the `Pyramid Renderers `_ chapter for extra details. As an example, let's update an :term:`endpoint` to use Pyramid 1.4's cool new :class:`pyramid.renderers.JSON` renderer which supports custom adapters. .. code-block:: python from pyramid.renderers import JSON json_renderer = JSON() json_renderer.add_adapter(datetime.datetime, lambda v: v.isoformat()) config.add_renderer('myjson', json_renderer) config.add_jsonrpc_endpoint('api', '/api', default_renderer='myjson') A ``default_renderer`` can be specified on an :term:`endpoint`, which will propagate to all methods attached to the endpoint. Optionally, an individual method can also override the renderer. View Mappers ------------ A view mapper is registered for JSON-RPC methods by default which will match the arguments from ``request.rpc_args`` to the parameters of the view. Optional arguments are allowed and an error will be returned if too many or too few arguments are supplied to the view. This default view mapper may be overridden by setting the ``default_mapper`` option on :func:`~pyramid_rpc.jsonrpc.add_jsonrpc_endpoint` or the ``mapper`` option when using :func:`~pyramid_rpc.jsonrpc.jsonrpc_method` or :func:`~pyramid_rpc.jsonrpc.add_jsonrpc_method`. HTTP GET and POST Support ------------------------- As of ``pyramid_rpc`` version 0.5, JSON-RPC requests can be made using HTTP GET. By default, an endpoint will accept requests from both ``GET`` and ``POST`` methods. This can be controlled on either the :term:`endpoint` or on an individual method by using the ``request_method`` predicate. For example, to limit requests to only ``POST`` requests: .. code-block:: python config.add_jsonrpc_endpoint('api', '/api', request_method='POST') Handling JSONP Requests ----------------------- Pyramid comes with a :class:`pyramid.renderers.JSONP` which can be registered for the endpoint, using the method described within :ref:`jsonrpc_custom_renderers`. .. _jsonrpc_api: API === .. automodule:: pyramid_rpc.jsonrpc .. autofunction:: includeme .. autofunction:: add_jsonrpc_endpoint .. autofunction:: add_jsonrpc_method .. autofunction:: jsonrpc_method Exceptions ---------- .. autoclass:: JsonRpcError .. autoclass:: JsonRpcParseError .. autoclass:: JsonRpcRequestInvalid .. autoclass:: JsonRpcMethodNotFound .. autoclass:: JsonRpcParamsInvalid .. autoclass:: JsonRpcInternalError