iro/view/jsonresource.py
branchdevel
changeset 297 93686b0c028b
--- /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 <iro@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()