| 184 | }}} |
| 185 | |
| 186 | == Alternative JsonRpc Implementation == |
| 187 | |
| 188 | This is the proven and working JSON-RPC Django handler developed incrementally since 2007 and deployed in production Pyjamas Web 2.0 applications. It is much shorter, simpler, easier to use and less cumbersome than the above, although it does not have support for GET (to view a list of methods) and does not have the same level of configurability. Importantly, the original request object is passed to all functions in the JSONRPC service, thus allowing the application to gain access to Django session information, and cookies etc. |
| 189 | |
| 190 | Usage examples are included inline in the source. Note in particular that the JSONRPCService class instance itself is handed to urlpatterns, and so all POST requests result in JSONRPCService's {{{__call__}}} method being called, resulting in a much simpler approach than the above. |
| 191 | |
| 192 | This code is maintained at http://groups.google.com/group/pyjamas-dev/files and a version is included in http://pyjs.org |
| 193 | |
| 194 | {{{ |
| 195 | # jsonrpc.py |
| 196 | # original code: http://trac.pyworks.org/pyjamas/wiki/DjangoWithPyJamas |
| 197 | # also from: http://www.pimentech.fr/technologies/outils |
| 198 | from django.utils import simplejson |
| 199 | import sys |
| 200 | |
| 201 | # JSONRPCService and jsonremote are used in combination to drastically |
| 202 | # simplify the provision of JSONRPC services. use as follows: |
| 203 | # |
| 204 | # from jsonrpc import JSONRPCService, jsonremote |
| 205 | # |
| 206 | # jsonservice = JSONRPCService() |
| 207 | # |
| 208 | # @jsonremote(jsonservice) |
| 209 | # def test(request, echo_param): |
| 210 | # return "echoing the param back: %s", echo_param |
| 211 | # |
| 212 | # then dump jsonservice into urlpatterns: |
| 213 | # (r'^service1/$', 'djangoapp.views.jsonservice'), |
| 214 | |
| 215 | def response(id, result): |
| 216 | return simplejson.dumps({'version': '1.1', 'id':id, |
| 217 | 'result':result, 'error':None}) |
| 218 | def error(id, code, message): |
| 219 | return simplejson.dumps({'id': id, 'version': '1.1', |
| 220 | 'error': {'name': 'JSONRPCError', |
| 221 | 'code': code, |
| 222 | 'message': message |
| 223 | } |
| 224 | }) |
| 225 | |
| 226 | class JSONRPCService: |
| 227 | def __init__(self, method_map={}): |
| 228 | self.method_map = method_map |
| 229 | |
| 230 | def add_method(self, name, method): |
| 231 | self.method_map[name] = method |
| 232 | |
| 233 | def __call__(self, request, extra=None): |
| 234 | # We do not yet support GET requests, something pyjamas does |
| 235 | # not use anyways. |
| 236 | data = simplejson.loads(request.raw_post_data) |
| 237 | # Altered to forward the request parameter when a member method |
| 238 | # is invocated <julien@pimentech.net> |
| 239 | id, method, params = data["id"],data["method"],[request,]+data["params"] |
| 240 | if method in self.method_map: |
| 241 | try: |
| 242 | result = self.method_map[method](*params) |
| 243 | return response(id, result) |
| 244 | except BaseException: |
| 245 | etype, eval, etb = sys.exc_info() |
| 246 | return error(id, 100, '%s: %s' %(etype.__name__, eval)) |
| 247 | except: |
| 248 | etype, eval, etb = sys.exc_info() |
| 249 | return error(id, 100, 'Exception %s: %s' %(etype, eval)) |
| 250 | else: |
| 251 | return error(id, 100, 'method "%s" does not exist' % method) |
| 252 | |
| 253 | |
| 254 | def jsonremote(service): |
| 255 | """Make JSONRPCService a decorator so that you can write : |
| 256 | |
| 257 | from jsonrpc import JSONRPCService |
| 258 | chatservice = JSONRPCService() |
| 259 | |
| 260 | @jsonremote(chatservice) |
| 261 | def login(request, user_name): |
| 262 | (...) |
| 263 | """ |
| 264 | def remotify(func): |
| 265 | if isinstance(service, JSONRPCService): |
| 266 | service.add_method(func.__name__, func) |
| 267 | else: |
| 268 | emsg = 'Service "%s" not found' % str(service.__name__) |
| 269 | raise NotImplementedError, emsg |
| 270 | return func |
| 271 | return remotify |
| 272 | |
| 273 | |
| 274 | }}} |