My favorites | Sign in
Project Home Wiki Issues Source
READ-ONLY: This project has been archived. For more information see this post.
Search
for
TwistedWeb2  
Updated Jan 8, 2012 by duncan.m...@gmail.com

JSON-RPC for twisted.web2

Dependencies

  • Twisted (+twisted.web2)
  • simplejson
  • setuptools

Notes

The original tests for twisted.web2.xmlrpc were also included/adapted and pass successfully.

Import

This is a stand-alone package that uses the adytum namespace, so if you have any other adytum code installed, you'll need to use setuptools' pkg_resource module:

>>> from pkg_resources import require
>>> require('Twisted-JSONRPC')
>>> from adytum.twisted.web2 import jsonrpc

If not, then you can simply use the standard import:

>>> from adytum.twisted.web2 import jsonrpc

Usage

Server

This is a direct copy from twisted.web2.xmlrpc and you use it identically, substituting JSONRPC and jsonrpc everywhere you see XMLRPC and xmlrpc. The docs for t.w2.xmlrpc are not up yet, but here are some example usages:

from twisted.web2 import server
from twisted.web2.channel import http
from twisted.application import service, internet

from adytum.twisted.web2 import jsonrpc

class Example(jsonrpc.JSONRPC):
    """An example object to be published."""

    addSlash = True

    def jsonrpc_echo(self, request, x):
        """Return all passed args."""
        return x

    def jsonrpc_add(self, request, a, b):
        """Return sum of arguments."""
        return a + b

site = server.Site(Example())
chan = http.HTTPFactory(site)
application = service.Application("Example JSON-RPC Server")
jsonrpcServer = internet.TCPServer(7080, chan)
jsonrpcServer.setServiceParent(application)

Save this as server.tac and run with the following command:

$ twistd -noy server.tac

Client

As far as I know, twisted.web2 doesn't have a (functional? good? any?) client yet. For this reason, t.w2.xmlrpc and a.t.w2.jsonrpc unit tests both use t.w for the client. We will do the same here:

from adytum.twisted.web.jsonrpc import Proxy
from twisted.internet import reactor

def printValue(value):
    print repr(value)
    reactor.stop()

def printError(error):
    print 'error', error
    reactor.stop()

proxy = Proxy('http://127.0.0.1:7080/')
proxy.callRemote('add', 3, 5).addCallbacks(printValue, printError)
reactor.run()

Save this file as client.py and run it from the command line. You should see an '8' printed to stdout.

Comment by russell....@gmail.com, Mar 15, 2008

You can use the client from jsolait.net with this, e.g.

from twisted.web2 import server, static
from twisted.web2.channel import http
from twisted.application import service, internet, strports

from adytum.twisted.web2 import jsonrpc

# Serve the inventory directory
toplevel = static.File("/var/www/jsolait")

class JsolaitTest(jsonrpc.JSONRPC):
	"""An example object to be published."""
	addSlash = True
	child_main=toplevel

	def jsonrpc_echo(self, request, x):
		"""Return all passed args."""
		return x

	def jsonrpc_add(self, request, a, b):
		"""Return sum of arguments."""
		return a + b

	def jsonrpc_system_listMethods(self, request):
		return ["echo", "add"]


application = service.Application("jsolait test server")

#Start the server on 7080
jsite = server.Site(JsolaitTest())
jsonrpcServer = internet.TCPServer(7080, http.HTTPFactory(jsite))
jsonrpcServer.setServiceParent(application)
<html>
	<head>
		<script type="text/javascript" src="/main/jsolait/jsolait.js">//foo</script>
		<script type="text/javascript" src="/main/jsolait/lib/urllib.js">//foo</script>
		<script type="text/javascript" src="/main/jsolait/lib/jsonrpc.js">//foo</script>
		<script type="text/javascript">
		var test=new jsolait.modules.jsonrpc.ServiceProxy("http://localhost:7080/", ["echo","add"]);
		</script>
	</head>
	<body>
		Loaded.
	</body>
</html>

Suggest you use firebug (e.g. via F12) to play with it.

Comment by russell....@gmail.com, Mar 15, 2008

Hm. I'm having problems with this: the returned value is put in a single element array rather than something like {id:blah, request:blah, error:null} and so is ignored by the JSON-RPC implementation.

Comment by russell....@gmail.com, Mar 16, 2008

A simple hack to try and make this work. Not sure why this isn't the normal behaviour, and I'd think an implementation that dealt with more cases and at least used ids in the returned objects would be necessary.

from twisted.web2 import server, static, channel
from twisted.application import service, internet

from adytum.twisted.web2 import jsonrpc

#for overridden _cbRender method.
from twisted.web2 import http, responsecode, http_headers
from adytum import jsonrpclib


# Serve the main directory
toplevel = static.File("/var/www/webapp/")

class JsolaitTest2(jsonrpc.JSONRPC):
	addSlash = True
	child_main=toplevel

	def jsonrpc_echo(self, request, x):
		"""Return all passed args."""
		return x

	def jsonrpc_add(self, request, a, b):
		"""Return sum of arguments."""
		return a + b

#Return values are wrong: returning an array with the returned value (e.g. if a+b==42, returning [42] for the add fn) rather than, e.g.
#{"id":'httpReq', "result":'hello echo', "error":null}
#Hack to fix this:
	def _cbRender(self, result, request):
		if not isinstance(result, jsonrpclib.Fault):
#Was result=(result,)
			result = {"result":result,"error":None}
		try:
			s = jsonrpclib.dumps(result)
		except:
			f = jsonrpclib.Fault(self.FAILURE, "can't serialize output")
			s = jsonrpclib.dumps(f)
		return http.Response(responsecode.OK, {'content-type': http_headers.MimeType('text', 'json')}, s)


#Start the JSONRPC server on 7080
site = server.Site(JsolaitTest2())
chan=channel.http.HTTPFactory(site)
application = service.Application("JSolait Test Server")
jsonrpcServer = internet.TCPServer(7080, chan)
jsonrpcServer.setServiceParent(application)

#$ twistd -noy main.tac
Powered by Google Project Hosting