| Version 6 (modified by , 16 years ago) ( diff ) |
|---|
JsonRpc
This is an easy-to-use implementation of a JSON-RPC handler for Django.
Features:
- Automatic SMD generation
- safe method resolution (ie, none of this stuff: http://secunia.com/advisories/14128/)
- No special urlconf or middleware magic
Example Django Usage
myproject/myapp/views.py:
from jsonrpc import JsonRpc, publicmethod
class MyRpcMethods(object):
url = reverse("myapp-rpc")
@publicmethod
def add(x, y):
return x+y
@publicmethod
def sub(x, y):
return x-y
def read_diary(self):
return "Here's all my secrets ..."
@publicmethod
def find_person(attribs):
filters = {}
for key in attribs.keys():
if key in ("first_name", "last_name"):
filters[key] = attribs[key]
return [
{"first_name": p.first_name, "last_name": p.last_name} \
for p in Person.objects.filter(**filters)
]
def my_rpc_view(request):
rpc = JsonRpc( MyRpcMethods() )
result = rpc.handle_request(request)
return result
Example Javascript client usage
var rpc = new dojo.rpc.JsonService("/myapp/rpc/");
rpc.add(3,4).addCallback(function(result) {
console.log(result);
});
>>> 7
rpc.callRemote("sub", [9,5]).addCallback(function(result) {
console.log(result);
});
>>> 4
rpc.callRemote("read_diary").addCallback(function(secrets) {
console.log(secrets);
});
>>> no such method
rpc.find_person({last_name: "Baggins"}).addCallback(function(result) {
dojo.forEach(result, function(person) {
console.log("Found: " + person.first_name, person.last_name);
});
});
>>> Found: Bilbo Baggins
>>> Found: Frodo Baggins
JsonRpc
jsonrpc.py
#
# Copyright (c) 2009, Ben Wilber (benwilber@gmail.com)
# All rights reserved
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License. You should have
# received a copy of the GPL license along with this program; if you
# did not, you can find it at http://www.gnu.org/
#
class publicmethod(object):
def __init__(self, method):
self.method = method
__public__ = True
def __call__(self, *args, **kwargs):
return self.method(*args, **kwargs)
def get_args(self):
from inspect import getargspec
return [ a for a in getargspec(self.method).args if (a != "self") ]
class JsonRpc(object):
def __init__(self, instance, allow_errors=True, report_methods=True):
self.instance = instance
self.allow_errors = allow_errors
self.report_methods = report_methods
if not hasattr(self.instance, "url"):
raise Exception("'url' not present in supplied instance")
def get_public_methods(self):
return [
m for m in dir(self.instance) if \
(getattr(self.instance, m).__class__.__name__ == "publicmethod") and \
(getattr(self.instance, m).__public__ == True)
]
def generate_smd(self):
self.smd = {
"serviceType": "JSON-RPC",
"serviceURL": self.instance.url,
"methods": []
}
if self.report_methods:
self.smd["methods"] += [
{"name": method, "parameters": getattr(self.instance, method).get_args()} \
for method in self.get_public_methods()
]
return simplejson.dumps(self.smd)
def dispatch(self, method, params):
if hasattr(self.instance, "dispatch") and \
callable(self.instance.dispatch):
return self.instance.dispatch(method, params)
elif method in self.get_public_methods():
return getattr(self.instance, method)(*params)
else:
return "no such method"
def serialize(self, raw_post_data):
raw_request = simplejson.loads(raw_post_data)
request_id = raw_request.get("id", 0)
request_method = raw_request.get("method")
request_params = raw_request.get("params", [])
response = {"id": request_id}
try:
response["result"] = self.dispatch(request_method, request_params)
except:
if self.allow_errors:
from sys import exc_type, exc_value
response["error"] = "%s: %s" % (exc_type, exc_value)
else:
response["error"] = "error"
return simplejson.dumps(response)
def handle_request(self, request):
if request.method == "POST" and \
len(request.POST) > 0:
return self.serialize(request.raw_post_data)
else:
return self.generate_smd()
Note:
See TracWiki
for help on using the wiki.