# tinyrpc: A modular RPC library

`tinyrpc` is a library for making and handling RPC calls in python. Its initial scope is handling jsonrpc, although it aims to be very well-documented and modular to make it easy to add support for further protocols.

A feature is support of multiple transports (or none at all) and providing clever syntactic sugar for writing dispatchers.

## Quickstart examples

The source contains all of these examples in a working fashion in the examples subfolder.

### HTTP based

A client making JSONRPC calls via HTTP (this requires `requests` to be installed):

    from tinyrpc.protocols.jsonrpc import JSONRPCProtocol
    from tinyrpc.transports.http import HttpPostClientTransport
    from tinyrpc import RPCClient

    rpc_client = RPCClient(
        JSONRPCProtocol(),
        HttpPostClientTransport('http://example.org/jsonrpc/2.0/')
    )

    time_server = rpc_client.get_proxy()

    # ...

    # call a method called 'get_time_in' with a single string argument
    time_in_berlin = time_server.get_time_in('Europe/Berlin')

These can be answered by a server implemented as follows:

    import gevent
    import gevent.wsgi
    import gevent.queue
    from tinyrpc.protocols.jsonrpc import JSONRPCProtocol
    from tinyrpc.transports.wsgi import WsgiServerTransport
    from tinyrpc.server.gevent import RPCServerGreenlets
    from tinyrpc.dispatch import RPCDispatcher

    dispatcher = RPCDispatcher()
    transport = WsgiServerTransport(queue_class=gevent.queue.Queue)

    # start wsgi server as a background-greenlet
    wsgi_server = gevent.wsgi.WSGIServer(('127.0.0.1', 80), transport.handle)
    gevent.spawn(wsgi_server.serve_forever)

    rpc_server = RPCServerGreenlets(
        transport,
        JSONRPCProtocol(),
        dispatcher
    )

    @dispatcher.public
    def reverse_string(s):
        return s[::-1]

    # in the main greenlet, run our rpc_server
    rpc_server.serve_forever()

### 0mq

An example using `zmq` is very similiar, differing only in the instantiation of the transport:

    import zmq

    from tinyrpc.protocols.jsonrpc import JSONRPCProtocol
    from tinyrpc.transports.zmq import ZmqClientTransport
    from tinyrpc import RPCClient

    ctx = zmq.Context()

    rpc_client = RPCClient(
        JSONRPCProtocol(),
        ZmqClientTransport.create(ctx, 'tcp://127.0.0.1:5001')
    )

    remote_server = rpc_client.get_proxy()

    # call a method called 'reverse_string' with a single string argument
    result = remote_server.reverse_string('Hello, World!')

    print "Server answered:", result

Matching server:

    import zmq

    from tinyrpc.protocols.jsonrpc import JSONRPCProtocol
    from tinyrpc.transports.zmq import ZmqServerTransport
    from tinyrpc.server import RPCServer
    from tinyrpc.dispatch import RPCDispatcher

    ctx = zmq.Context()
    dispatcher = RPCDispatcher()
    transport = ZmqServerTransport.create(ctx, 'tcp://127.0.0.1:5001')

    rpc_server = RPCServer(
        transport,
        JSONRPCProtocol(),
        dispatcher
    )

    @dispatcher.public
    def reverse_string(s):
        return s[::-1]

    rpc_server.serve_forever()

## Further examples

In The protocol layer, you can find client and server examples on how to use just the protocol parsing parts of `tinyrpc`.

The `RPCDispatcher` should be useful on its own (or at least easily replaced with one of your choosing), see Dispatching for details.

## Table of contents

- Structure of tinyrpc
- The protocol layer
  - Batch protocols
  - Supported protocols
  - Example
- Dispatching
  - Examples
  - API reference
- Transports
  - Transport implementations
- RPC Client
- Server implementations
  - `tinyrpc.server.gevent.RPCServerGreenlets`
- Exception reference

## People

### Creator

- Marc Brinkmann: https://github.com/mbr

### Maintainer

- Leo Noordergraaf: https://github.com/lnoor

### Contributors

- Guilherme Salgado: https://github.com/gsalgado

- jnnk: https://github.com/jnnk

- Satoshi Kobayashi: https://github.com/satosi-k