Skip to content

sancelot/jsonrpctcp

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

17 Commits
 
 
 
 
 
 
 
 

Repository files navigation

JSONRPCTCP
==========

This project is just an implementation of the JSON-RPC protocol over
TCP. It supports the JSON-RPC 2.0 specification, but it is not (at 
this point) backwards-compatible with 1.0, because I like 2.0 more. :)

It also supports basic encryption and decryption via pycrypto if it is 
installed. Alternatively, you can wrap your own cipher class as long 
as it utilizes the 'new', 'encrypt', and 'decrypt' methods in the same
manner as the Crypto.Cipher classes in the pycrypto library.

It's early on, so feedback is greatly desired. You can hit the 
Google Groups site at http://groups.google.com/group/jsonrpctcp or
email [email protected] if you have any questions, advice, 
patches, or just need a friend. :)

JSONRPCTCP is licensed under the Apache Licence, Version 2.0
(http://www.apache.org/licenses/LICENSE-2.0.html).

Requirements
============
* Python 2.5+
* SimpleJSON on Python < 2.6
* PyCrypto (optional) for encryption support

Installation
============

    python setup.py build
    sudo python setup.py install

Tests
=====
The jsonrpctcp library contains nearly-verbatim tests from the
JSON-RPC 2.0 Specification Document. 
(http://groups.google.com/group/json-rpc/web/json-rpc-2-0)

After installation, or from the same directory as the setup.py
file and this README, you can run the tests like so:

    python -m jsonrpctcp.tests

If all is well, you should see 13ish tests that ran successfully.

Additionally, you can spin up a test server in one terminal
and run a few test client methods in another with the following
instructions. (These tests are not as detailed, but it's there
for whatever purpose.)

Start server (hit Ctrl-C or Ctrl-Break in Windows to stop): 
    python -m jsonrpctcp.server
   
Start client in another terminal:
    python -m jsonrpctcp.client

The client terminal should print out a short list of tests it
performed.

Usage Examples
==============
Below, you'll find simple uses of both client and server. I'd love
to hear feedback on the usability of this interface, and whether
certain controls / attributes should be more accessible.

Client Usage
============

This should be pretty familiar to users of xmlrpclib, with only a few
name differences. The connect method takes the IP address / machine name,
the port of the service, and an optional key if encryption is desired. 
Encryption requires the pycrypto library or a cipher-like class as the
config.crypt value. See configuration info below for details.

Client examples:

    # Simple example
    from jsonrpctcp import connect
    
    conn = connect('localhost', 8001)
	# Optionally, you can add a third string parameter which is the
	# encryption key used on the server.
	conn = connect('localhost', 8001, '12345abcdef67890')
	# Just use simple dot-syntax to call methods. Don't use a method
	# that starts with an underscore -- those are automatically private.
    result = conn.add(1, 2)
    # ...and should be 3. :)
    
    # Notification example -- it uses the '_notification' attribute
    # of the client connection to flag that this request doesn't need
    # a response.
    conn._notification.add(5, 6)
    # Null response, because it's a notification. It actually closes the
    # connection after submitting the full request.
    
    # Batch example -- it uses the '_batch' method of the client
    # connection to return a new, batch-enabled connection. It 
    # automatically orders the reponses and skips notifications.
    batch = conn._batch()
    batch.add(y=5, x=6)
    batch._notification.add(6,4)
    batch.namespace.echo("Repeat me!")
    result = batch()
    for i in result:
        print i
    # Should print out 11, and then "Repeat me!", skipping the 
    # notification.

    # You can access the request and response data with
    # history.request and history.response . These are the
    # string values after any encryption / decryption, so you'll 
    # need to use a JSON library to decode them.
	from jsonrpctcp import history
	result = conn.sum(5, 6)
	print history.request
	>>> {"params": [5, 6], "jsonrpc": "2.0", "method": "sum", "id": 
	    "2fa1a919-5a14-44a8-bb52-af16757b12ee"}
	print history.response
	>>> {"jsonrpc": "2.0", "result": 11, "id": 
		"2fa1a919-5a14-44a8-bb52-af16757b12ee"}
	
	# You can also see the responses via the logger:
	from jsonrpctcp import logger
	import logging
	logger.setLevel(logging.DEBUG)
	logger.addHandler(logging.StreamHandler())
	result = conn.sum(5, 6)
	# The following prints out:
	CLIENT | REQUEST: {"params": [5, 6], "jsonrpc": "2.0", "method": "sum", 
		"id": "734941ad-bc30-4572-9e5f-e974fd04ef1c"}
	CLIENT | RESPONSE: {"jsonrpc": "2.0", "result": 11, "id": 
		"734941ad-bc30-4572-9e5f-e974fd04ef1c"}
    

Server Usage
============

The server is bound to a socket, and the handler function(s) can be passed 
in manually one by one, or (preferred) you can subclass the Handler object
and use that. It threads (not forks) the individual requests for you, but
if you don't use the start_server() shortcut, you'll have to thread the 
actual server startup yourself if you want to do anything after it starts.

All you should need to enable encrypted support is pycrypto installed, and
to set the config.secret to an appropriate key string. See below for config
details.

Server examples:
    # Function handler example
    from jsonrpctcp.server import Server
    from jsonrpctcp import config
    
    config.verbose = True
            
    def add(x, y):
        return x+y
        
    def echo(message):
        return message
        
    server = Server(('localhost', 8001))
    server.add_handler(add)
    server.add_handler(echo, 'namespace.echo')
    server.serve() # blocks
        
    ------------------

	# Class handler example
    from jsonrpctcp import start_server
    from jsonrpctcp.handler import Handler
    import time
    
    class NewHandler(Handler):
        def echo(self, message):
            return message
   
    # This automatically threads the server instance.     
    server = start_server('localhost', 8001, NewHandler)
    
    while True:
        # Do whatever you need for polling
        time.sleep(5)
    
    # You'll have to thread the start up yourself this way, if you need it.
    
Configuration
=============

There's a simple configuration object that has a few attributes. You can
change them per the following:

    from jsonrpctcp import config
    
    config.verbose = True # default is False
    config.timeout = 30 # default is 5
    config.buffer = 4096 # default is 1024
    config.crypt = DES3 # default is AES if pycrypto is installed
	config.secret = '12345abcdef67890' 
	# default is none, 'secret' indicates that the server should
	# decrypt requests and encrypt responses.
    
These may not be the best defaults, any thoughts would be appreciated.

Debugging
=========

If you want to see the actual requests, responses, etc. you'll need to
add a handler and set a level to the jsonrpctcp logger. This uses the
basic python logging module, so it should be fairly familiar:

	import loggging
	from jsonrpctcp import logger
	logger.addHandler(logging.StreamHandler()) # sends to stdout
	logger.setLevel(logging.DEBUG)
	
TODO
====
* Replace threaded socket requests with epoll / select fallback.
* Stabilize and get on PyPI.
* Add more unit tests.
* Generally make more awesome.

About

A Python TCP socket implementation of JSON-RPC (v2)

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Python 100.0%