JSON-RPC Example
================

.. contents::

:author: Ian Bicking

Introduction
------------

This is an example of how to write a web service using WebOb.  The
example shows how to create a `JSON-RPC <http://json-rpc.org/>`_
endpoint using WebOb and the `simplejson
<http://www.undefined.org/python/#simplejson>`_ JSON library.  This
also shows how to use WebOb as a client library using `WSGIProxy
<http://pythonpaste.org/wsgiproxy/>`_.

While this example presents JSON-RPC, this is not an endorsement of
JSON-RPC.  In fact I don't like JSON-RPC.  It's unnecessarily
un-RESTful, and modelled too closely on `XML-RPC
<http://www.xmlrpc.com/>`_.

Code
----

The finished code for this is available in
`docs/json-example-code/jsonrpc.py
<https://github.com/Pylons/webob/tree/master/docs/jsonrpc-example-code/jsonrpc.py>`_
-- you can run that file as a script to try it out, or import it.

Concepts
--------

JSON-RPC wraps an object, allowing you to call methods on that object
and get the return values.  It also provides a way to get error
responses.

The `specification
<http://json-rpc.org/wd/JSON-RPC-1-1-WD-20060807.html>`_ goes into the
details (though in a vague sort of way).  Here's the basics:

* All access goes through a POST to a single URL.

* The POST contains a JSON body that looks like::

   {"method": "methodName",
    "id": "arbitrary-something",
    "params": [arg1, arg2, ...]}

* The ``id`` parameter is just a convenience for the client to keep
  track of which response goes with which request.  This makes
  asynchronous calls (like an XMLHttpRequest) easier.  We just send
  the exact same id back as we get, we never look at it.

* The response is JSON.  A successful response looks like::

    {"result": the_result,
     "error": null,
     "id": "arbitrary-something"}

* The error response looks like::

    {"result": null,
     "error": {"name": "JSONRPCError",
               "code": (number 100-999),
               "message": "Some Error Occurred",
               "error": "whatever you want\n(a traceback?)"},
     "id": "arbitrary-something"}

* It doesn't seem to indicate if an error response should have a 200
  response or a 500 response.  So as not to be completely stupid about
  HTTP, we choose a 500 resonse, as giving an error with a 200
  response is irresponsible.

Infrastructure
--------------

To make this easier to test, we'll set up a bit of infrastructure.
This will open up a server (using `wsgiref
<http://python.org/doc/current/lib/module-wsgiref.simpleserver.html>`_)
and serve up our application (note that *creating* the application is
left out to start with):

.. code-block:: python

    import sys

    def main(args=None):
        import optparse
        from wsgiref import simple_server
        parser = optparse.OptionParser(
            usage="%prog [OPTIONS] MODULE:EXPRESSION")
        parser.add_option(
            '-p', '--port', default='8080',
            help='Port to serve on (default 8080)')
        parser.add_option(
            '-H', '--host', default='127.0.0.1',
            help='Host to serve on (default localhost; 0.0.0.0 to make public)')
        if args is None:
            args = sys.argv[1:]
        options, args = parser.parse_args()
        if not args or len(args) > 1:
            print 'You must give a single object reference'
            parser.print_help()
            sys.exit(2)
        app = make_app(args[0])
        server = simple_server.make_server(
            options.host, int(options.port),
            app)
        print 'Serving on http://%s:%s' % (options.host, options.port)
        server.serve_forever()

    if __name__ == '__main__':
        main()

I won't describe this much.  It starts a server, serving up just the
app created by ``make_app(args[0])``.  ``make_app`` will have to load
up the object and wrap it in our WSGI/WebOb wrapper.  We'll be calling
that wrapper ``JSONRPC(obj)``, so here's how it'll go:

.. code-block:: python

    def make_app(expr):
        module, expression = expr.split(':', 1)
        __import__(module)
        module = sys.modules[module]
        obj = eval(expression, module.__dict__)
        return JsonRpcApp(obj)

We use ``__import__(module)`` to import the module, but its return
value is wonky.  We can find the thing it imported in ``sys.modules``
(a dictionary of all the loaded modules).  Then we evaluate the second
part of the expression in the namespace of the module.  This lets you
do something like ``smtplib:SMTP('localhost')`` to get a fully
instantiated SMTP object.

That's all the infrastructure we'll need for the server side.  Now we
just have to implement ``JsonRpcApp``.

The Application Wrapper
-----------------------

Note that I'm calling this an "application" because that's the
terminology WSGI uses.  Everything that gets *called* is an
"application", and anything that calls an application is called a
"server".

The instantiation of the server is already figured out:

.. code-block:: python

    class JsonRpcApp(object):

        def __init__(self, obj):
            self.obj = obj

        def __call__(self, environ, start_response):
            ... the WSGI interface ...

So the server is an instance bound to the particular object being
exposed, and ``__call__`` implements the WSGI interface.

We'll start with a simple outline of the WSGI interface, using a kind
of standard WebOb setup:

.. code-block:: python

    from webob import Request, Response
    from webob import exc

    class JsonRpcApp(object):
        ...
        def __call__(self, environ, start_response):
            req = Request(environ)
            try:
                resp = self.process(req)
            except ValueError, e:
                resp = exc.HTTPBadRequest(str(e))
            except exc.HTTPException, e:
                resp = e
            return resp(environ, start_response)

We first create a request object.  The request object just wraps the
WSGI environment.  Then we create the response object in the
``process`` method (which we still have to write).  We also do some
exception catching.  We'll turn any ``ValueError`` into a ``400 Bad
Request`` response.  We'll also let ``process`` raise any
``web.exc.HTTPException`` exception.  There's an exception defined in
that module for all the HTTP error responses, like ``405 Method Not
Allowed``.  These exceptions are themselves WSGI applications (as is
``webob.Response``), and so we call them like WSGI applications and
return the result.

The ``process`` method
----------------------

The ``process`` method of course is where all the fancy stuff
happens.  We'll start with just the most minimal implementation, with
no error checking or handling:

.. code-block:: python

    from simplejson import loads, dumps

    class JsonRpcApp(object):
        ...
        def process(self, req):
            json = loads(req.body)
            method = json['method']
            params = json['params']
            id = json['id']
            method = getattr(self.obj, method)
            result = method(*params)
            resp = Response(
                content_type='application/json',
                body=dumps(dict(result=result,
                                error=None,
                                id=id)))
            return resp

As long as the request is properly formed and the method doesn't raise
any exceptions, you are pretty much set.  But of course that's not a
reasonable expectation.  There's a whole bunch of things that can go
wrong.  For instance, it has to be a POST method:

.. code-block:: python

    if not req.method == 'POST':
        raise exc.HTTPMethodNotAllowed(
            "Only POST allowed",
            allowed='POST')

And maybe the request body doesn't contain valid JSON:

.. code-block:: python

    try:
        json = loads(req.body)
    except ValueError, e:
        raise ValueError('Bad JSON: %s' % e)

And maybe all the keys aren't in the dictionary:

.. code-block:: python

    try:
        method = json['method']
        params = json['params']
        id = json['id']
    except KeyError, e:
        raise ValueError(
            "JSON body missing parameter: %s" % e)

And maybe it's trying to acces a private method (a method that starts
with ``_``) -- that's not just a bad request, we'll call that case
``403 Forbidden``.

.. code-block:: python

    if method.startswith('_'):
        raise exc.HTTPForbidden(
            "Bad method name %s: must not start with _" % method)

And maybe ``json['params']`` isn't a list:

.. code-block:: python

    if not isinstance(params, list):
        raise ValueError(
            "Bad params %r: must be a list" % params)

And maybe the method doesn't exist:

.. code-block:: python

    try:
        method = getattr(self.obj, method)
    except AttributeError:
        raise ValueError(
            "No such method %s" % method)

The last case is the error we actually can expect: that the method
raises some exception.

.. code-block:: python

    try:
        result = method(*params)
    except:
        tb = traceback.format_exc()
        exc_value = sys.exc_info()[1]
        error_value = dict(
            name='JSONRPCError',
            code=100,
            message=str(exc_value),
            error=tb)
        return Response(
            status=500,
            content_type='application/json',
            body=dumps(dict(result=None,
                            error=error_value,
                            id=id)))

That's a complete server.

The Complete Code
-----------------

Since we showed all the error handling in pieces, here's the complete
code:

.. code-block:: python

    from webob import Request, Response
    from webob import exc
    from simplejson import loads, dumps
    import traceback
    import sys

    class JsonRpcApp(object):
        """
        Serve the given object via json-rpc (http://json-rpc.org/)
        """

        def __init__(self, obj):
            self.obj = obj

        def __call__(self, environ, start_response):
            req = Request(environ)
            try:
                resp = self.process(req)
            except ValueError, e:
                resp = exc.HTTPBadRequest(str(e))
            except exc.HTTPException, e:
                resp = e
            return resp(environ, start_response)

        def process(self, req):
            if not req.method == 'POST':
                raise exc.HTTPMethodNotAllowed(
                    "Only POST allowed",
                    allowed='POST')
            try:
                json = loads(req.body)
            except ValueError, e:
                raise ValueError('Bad JSON: %s' % e)
            try:
                method = json['method']
                params = json['params']
                id = json['id']
            except KeyError, e:
                raise ValueError(
                    "JSON body missing parameter: %s" % e)
            if method.startswith('_'):
                raise exc.HTTPForbidden(
                    "Bad method name %s: must not start with _" % method)
            if not isinstance(params, list):
                raise ValueError(
                    "Bad params %r: must be a list" % params)
            try:
                method = getattr(self.obj, method)
            except AttributeError:
                raise ValueError(
                    "No such method %s" % method)
            try:
                result = method(*params)
            except:
                text = traceback.format_exc()
                exc_value = sys.exc_info()[1]
                error_value = dict(
                    name='JSONRPCError',
                    code=100,
                    message=str(exc_value),
                    error=text)
                return Response(
                    status=500,
                    content_type='application/json',
                    body=dumps(dict(result=None,
                                    error=error_value,
                                    id=id)))
            return Response(
                content_type='application/json',
                body=dumps(dict(result=result,
                                error=None,
                                id=id)))

The Client
----------

It would be nice to have a client to test out our server.  Using
`WSGIProxy`_ we can use WebOb
Request and Response to do actual HTTP connections.

The basic idea is that you can create a blank Request:

.. code-block:: python

    >>> from webob import Request
    >>> req = Request.blank('http://python.org')

Then you can send that request to an application:

.. code-block:: python

    >>> from wsgiproxy.exactproxy import proxy_exact_request
    >>> resp = req.get_response(proxy_exact_request)

This particular application (``proxy_exact_request``) sends the
request over HTTP:

.. code-block:: python

    >>> resp.content_type
    'text/html'
    >>> resp.body[:10]
    '<!DOCTYPE '

So we're going to create a proxy object that constructs WebOb-based
jsonrpc requests, and sends those using ``proxy_exact_request``.

The Proxy Client
----------------

The proxy client is instantiated with its base URL.  We'll also let
you pass in a proxy application, in case you want to do local requests
(e.g., to do direct tests against a ``JsonRpcApp`` instance):

.. code-block:: python

    class ServerProxy(object):

        def __init__(self, url, proxy=None):
            self._url = url
            if proxy is None:
                from wsgiproxy.exactproxy import proxy_exact_request
                proxy = proxy_exact_request
            self.proxy = proxy

This ServerProxy object itself doesn't do much, but you can call methods on
it.  We can intercept any access ``ServerProxy(...).method`` with the
magic function ``__getattr__``.  Whenever you get an attribute that
doesn't exist in an instance, Python will call
``inst.__getattr__(attr_name)`` and return that.  When you *call* a
method, you are calling the object that ``.method`` returns.  So we'll
create a helper object that is callable, and our ``__getattr__`` will
just return that:

.. code-block:: python

    class ServerProxy(object):
        ...
        def __getattr__(self, name):
            # Note, even attributes like __contains__ can get routed
            # through __getattr__
            if name.startswith('_'):
                raise AttributeError(name)
            return _Method(self, name)

    class _Method(object):
        def __init__(self, parent, name):
            self.parent = parent
            self.name = name

Now when we call the method we'll be calling ``_Method.__call__``, and
the HTTP endpoint will be ``self.parent._url``, and the method name
will be ``self.name``.

Here's the code to do the call:

.. code-block:: python

    class _Method(object):
        ...

        def __call__(self, *args):
            json = dict(method=self.name,
                        id=None,
                        params=list(args))
            req = Request.blank(self.parent._url)
            req.method = 'POST'
            req.content_type = 'application/json'
            req.body = dumps(json)
            resp = req.get_response(self.parent.proxy)
            if resp.status_code != 200 and not (
                resp.status_code == 500
                and resp.content_type == 'application/json'):
                raise ProxyError(
                    "Error from JSON-RPC client %s: %s"
                    % (self._url, resp.status),
                    resp)
            json = loads(resp.body)
            if json.get('error') is not None:
                e = Fault(
                    json['error'].get('message'),
                    json['error'].get('code'),
                    json['error'].get('error'),
                    resp)
                raise e
            return json['result']

We raise two kinds of exceptions here.  ``ProxyError`` is when
something unexpected happens, like a ``404 Not Found``.  ``Fault`` is
when a more expected exception occurs, i.e., the underlying method
raised an exception.

In both cases we'll keep the response object around, as that can be
interesting.  Note that you can make exceptions have any methods or
signature you want, which we'll do:

.. code-block:: python

    class ProxyError(Exception):
        """
        Raised when a request via ServerProxy breaks
        """
        def __init__(self, message, response):
            Exception.__init__(self, message)
            self.response = response

    class Fault(Exception):
        """
        Raised when there is a remote error
        """
        def __init__(self, message, code, error, response):
            Exception.__init__(self, message)
            self.code = code
            self.error = error
            self.response = response
        def __str__(self):
            return 'Method error calling %s: %s\n%s' % (
                self.response.request.url,
                self.args[0],
                self.error)

Using Them Together
-------------------

Good programmers start with tests.  But at least we'll end with a
test.  We'll use `doctest
<http://python.org/doc/current/lib/module-doctest.html>`_ for our
tests.  The test is in `docs/json-example-code/test_jsonrpc.txt
<https://github.com/Pylons/webob/tree/master/docs/jsonrpc-example-code/test_jsonrpc.txt>`_
and you can run it with `docs/json-example-code/test_jsonrpc.py
<https://github.com/Pylons/webob/tree/master/docs/jsonrpc-example-code/test_jsonrpc.py>`_,
which looks like:

.. code-block:: python

    if __name__ == '__main__':
        import doctest
        doctest.testfile('test_jsonrpc.txt')

As you can see, it's just a stub to run the doctest.  We'll need a
simple object to expose.  We'll make it real simple:

.. code-block:: python

    >>> class Divider(object):
    ...     def divide(self, a, b):
    ...        return a / b

Then we'll get the app setup:

.. code-block:: python

    >>> from jsonrpc import *
    >>> app = JsonRpcApp(Divider())

And attach the client *directly* to it:

.. code-block:: python

    >>> proxy = ServerProxy('http://localhost:8080', proxy=app)

Because we gave the app itself as the proxy, the URL doesn't actually
matter.

Now, if you are used to testing you might ask: is this kosher?  That
is, we are shortcircuiting HTTP entirely.  Is this a realistic test?

One thing you might be worried about in this case is that there are
more shared objects than you'd have with HTTP.  That is, everything
over HTTP is serialized to headers and bodies.  Without HTTP, we can
send stuff around that can't go over HTTP.  This *could* happen, but
we're mostly protected because the only thing the application's share
is the WSGI ``environ``.  Even though we use a ``webob.Request``
object on both side, it's not the *same* request object, and all the
state is studiously kept in the environment.  We *could* share things
in the environment that couldn't go over HTTP.  For instance, we could
set ``environ['jsonrpc.request_value'] = dict(...)``, and avoid
``simplejson.dumps`` and ``simplejson.loads``.  We *could* do that,
and if we did then it is possible our test would work even though the
libraries were broken over HTTP.  But of course inspection shows we
*don't* do that.  A little discipline is required to resist playing clever
tricks (or else you can play those tricks and do more testing).
Generally it works well.

So, now we have a proxy, lets use it:

.. code-block:: python

    >>> proxy.divide(10, 4)
    2
    >>> proxy.divide(10, 4.0)
    2.5

Lastly, we'll test a couple error conditions.  First a method error:

.. code-block:: python

    >>> proxy.divide(10, 0) # doctest: +ELLIPSIS
    Traceback (most recent call last):
       ...
    Fault: Method error calling http://localhost:8080: integer division or modulo by zero
    Traceback (most recent call last):
      File ...
        result = method(*params)
      File ...
        return a / b
    ZeroDivisionError: integer division or modulo by zero
    <BLANKLINE>

It's hard to actually predict this exception, because the test of the
exception itself contains the traceback from the underlying call, with
filenames and line numbers that aren't stable.  We use ``# doctest:
+ELLIPSIS`` so that we can replace text we don't care about with
``...``.  This is actually figured out through copy-and-paste, and
visual inspection to make sure it looks sensible.

The other exception can be:

.. code-block:: python

    >>> proxy.add(1, 1)
    Traceback (most recent call last):
        ...
    ProxyError: Error from JSON-RPC client http://localhost:8080: 400 Bad Request

Here the exception isn't a JSON-RPC method exception, but a more basic
ProxyError exception.

Conclusion
----------

Hopefully this will give you ideas about how to implement web services
of different kinds using WebOb.  I hope you also can appreciate the
elegance of the symmetry of the request and response objects, and the
client and server for the protocol.

Many of these techniques would be better used with a `RESTful
<http://en.wikipedia.org/wiki/Representational_State_Transfer>`_
service, so do think about that direction if you are implementing your
own protocol.
