diff -r a73bbc1d8b4b -r 93686b0c028b iro/view/jsonresource.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/iro/view/jsonresource.py Thu Sep 27 14:25:41 2012 +0200 @@ -0,0 +1,140 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2012 netzguerilla.net +# +# This file is part of Iro. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy of +# this software and associated documentation files (the "Software"), to deal in +# the Software without restriction, including without limitation the rights to use, +# copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the +# #Software, and to permit persons to whom the Software is furnished to do so, +# subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +from twisted.web import resource, server, http +from twisted.python import log, failure +from twisted.internet import defer + +from ..controller.viewinterface import Interface +from ..error import ValidateException + +try: + import json +except ImportError: + import simplejson as json + + +class TwistedInterface(Interface): + """Class that addes needed function for JSON""" + def __init__(self): + Interface.__init__(self) + + def listMethods(self): + """Since we override lookupProcedure, its suggested to override + listProcedures too. + """ + return self.listProcedures() + + + def listProcedures(self): + """returns a list of all functions that are allowed to call via XML-RPC.""" + return ['listMethods','status','sms','fax','mail','routes','defaultRoute','bill','telnumber','email'] + +class MethodFactory(resource.Resource): + def __init__(self,method,twistedInterface): + self.method = method + self.twistedInterface = twistedInterface + + def render(self,request): + try: + args = [] + if request.getHeader('Content-Type') == 'application/x-www-form-urlencoded': + args = {} + for a in request.args: + value = request.args[a] + if a != "recipients" and len(value) == 1: + value = value[0] + args[a] = value + elif request.getHeader('Content-Type') == 'application/json': + content = request.content.read() + if content: + args = json.loads(content) + if args is None: + args = [] + else: + request.setResponseCode(http.NOT_ACCEPTABLE) + return "Only application/x-www-form-urlencoded or application/json ist allowed for Content-Type" + if isinstance(args,list): + d = defer.maybeDeferred(getattr(self.twistedInterface,self.method),*args) + else: + d = defer.maybeDeferred(getattr(self.twistedInterface,self.method), **args) + d.addCallback(self._cbRender, request) + d.addErrback(self._ebRender, request) + d.addBoth(lambda _: request.finish()) + return server.NOT_DONE_YET + except Exception: + log.err(failure.Failure()) + request.setResponseCode(http.INTERNAL_SERVER_ERROR) + err= { + "code" : 999, + "msg" : "Unknown error.", + } + request.setHeader('Content-Type', 'application/json') + return json.dumps({"status":False, "error":err}) + + + def _cbRender(self,result,request): + request.setHeader('Content-Type', 'application/json') + request.write(json.dumps({"status":True, "result":result})) + + def _ebRender(self, failure, request): + if isinstance(failure.value, ValidateException): + request.setResponseCode(http.BAD_REQUEST) + else: + request.setResponseCode(http.INTERNAL_SERVER_ERROR) + + err= { + "code" : 999, + "msg" : "Unknown error.", + } + + try: + err["code"]=failure.value.code + err["msg"]=failure.value.msg + except Exception: + log.err(failure) + pass + request.setHeader('Content-Type', 'application/json') + request.write(json.dumps({"status":False, "error":err})) + +class JSONFactory(resource.Resource): + """JSON factory""" + def __init__(self): + resource.Resource.__init__(self) + self.twistedInterface = TwistedInterface() + for method in self.twistedInterface.listProcedures(): + self.putChild(method, MethodFactory(method, self.twistedInterface)) + + +def appendResource(root): + """adding JSON to root.""" + root.putChild('json', JSONFactory()) + +if __name__ == '__main__': + from twisted.web import resource + from twisted.internet import reactor + + root = resource.Resource() + root = appendResource(root) + reactor.listenTCP(7080, server.Site(root)) + reactor.run()