iro/view/jsonresource.py
branchdevel
changeset 297 93686b0c028b
equal deleted inserted replaced
296:a73bbc1d8b4b 297:93686b0c028b
       
     1 # -*- coding: utf-8 -*-
       
     2 
       
     3 # Copyright (c) 2012 netzguerilla.net <iro@netzguerilla.net>
       
     4 #
       
     5 # This file is part of Iro.
       
     6 #
       
     7 # Permission is hereby granted, free of charge, to any person obtaining a copy of
       
     8 # this software and associated documentation files (the "Software"), to deal in
       
     9 # the Software without restriction, including without limitation the rights to use,
       
    10 # copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
       
    11 # #Software, and to permit persons to whom the Software is furnished to do so,
       
    12 # subject to the following conditions:
       
    13 #
       
    14 # The above copyright notice and this permission notice shall be included in
       
    15 # all copies or substantial portions of the Software.
       
    16 #
       
    17 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
       
    18 # INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
       
    19 # PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
       
    20 # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
       
    21 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
       
    22 # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
       
    23 
       
    24 from twisted.web import resource, server, http
       
    25 from twisted.python import log, failure
       
    26 from twisted.internet import defer
       
    27 
       
    28 from ..controller.viewinterface import Interface
       
    29 from ..error import ValidateException
       
    30 
       
    31 try:
       
    32     import json
       
    33 except ImportError:
       
    34     import simplejson as json
       
    35 
       
    36 
       
    37 class TwistedInterface(Interface):
       
    38     """Class that addes needed function for JSON"""
       
    39     def __init__(self):
       
    40         Interface.__init__(self)
       
    41 
       
    42     def listMethods(self):
       
    43         """Since we override lookupProcedure, its suggested to override
       
    44         listProcedures too.
       
    45         """
       
    46         return self.listProcedures()
       
    47 
       
    48 
       
    49     def listProcedures(self):
       
    50         """returns a list of all functions that are allowed to call via XML-RPC."""
       
    51         return ['listMethods','status','sms','fax','mail','routes','defaultRoute','bill','telnumber','email']
       
    52 
       
    53 class MethodFactory(resource.Resource):
       
    54     def __init__(self,method,twistedInterface):
       
    55         self.method = method
       
    56         self.twistedInterface = twistedInterface
       
    57 
       
    58     def render(self,request):
       
    59         try:
       
    60             args = []
       
    61             if request.getHeader('Content-Type') == 'application/x-www-form-urlencoded':
       
    62                 args = {}
       
    63                 for a in request.args:
       
    64                     value = request.args[a]
       
    65                     if a != "recipients" and len(value) == 1:
       
    66                         value = value[0]
       
    67                     args[a] = value
       
    68             elif request.getHeader('Content-Type') == 'application/json':
       
    69                 content = request.content.read()
       
    70                 if content:
       
    71                     args = json.loads(content)
       
    72                 if args is None:
       
    73                     args = []
       
    74             else:
       
    75                 request.setResponseCode(http.NOT_ACCEPTABLE)
       
    76                 return "Only application/x-www-form-urlencoded or application/json ist allowed for Content-Type"
       
    77             if isinstance(args,list):
       
    78                 d =  defer.maybeDeferred(getattr(self.twistedInterface,self.method),*args)
       
    79             else:
       
    80                 d =  defer.maybeDeferred(getattr(self.twistedInterface,self.method), **args)
       
    81             d.addCallback(self._cbRender, request)
       
    82             d.addErrback(self._ebRender, request)
       
    83             d.addBoth(lambda _: request.finish())
       
    84             return server.NOT_DONE_YET
       
    85         except Exception:
       
    86             log.err(failure.Failure())
       
    87             request.setResponseCode(http.INTERNAL_SERVER_ERROR)
       
    88             err= {
       
    89                     "code" : 999,
       
    90                     "msg"  : "Unknown error.",
       
    91                 }
       
    92             request.setHeader('Content-Type', 'application/json')
       
    93             return json.dumps({"status":False, "error":err})
       
    94 
       
    95 
       
    96     def _cbRender(self,result,request):
       
    97         request.setHeader('Content-Type', 'application/json')
       
    98         request.write(json.dumps({"status":True, "result":result}))
       
    99 
       
   100     def _ebRender(self, failure, request):
       
   101         if isinstance(failure.value, ValidateException):
       
   102             request.setResponseCode(http.BAD_REQUEST)
       
   103         else:
       
   104             request.setResponseCode(http.INTERNAL_SERVER_ERROR)
       
   105 
       
   106         err= {
       
   107                 "code" : 999,
       
   108                 "msg"  : "Unknown error.",
       
   109             }
       
   110 
       
   111         try:
       
   112             err["code"]=failure.value.code
       
   113             err["msg"]=failure.value.msg
       
   114         except Exception:
       
   115             log.err(failure)
       
   116             pass
       
   117         request.setHeader('Content-Type', 'application/json')
       
   118         request.write(json.dumps({"status":False, "error":err}))
       
   119 
       
   120 class JSONFactory(resource.Resource):
       
   121     """JSON factory"""
       
   122     def __init__(self):
       
   123         resource.Resource.__init__(self)
       
   124         self.twistedInterface = TwistedInterface()
       
   125         for method in self.twistedInterface.listProcedures():
       
   126             self.putChild(method, MethodFactory(method, self.twistedInterface))
       
   127 
       
   128 
       
   129 def appendResource(root):
       
   130     """adding JSON to root."""
       
   131     root.putChild('json', JSONFactory())
       
   132 
       
   133 if __name__ == '__main__':
       
   134     from twisted.web import resource
       
   135     from twisted.internet import reactor
       
   136 
       
   137     root = resource.Resource()
       
   138     root = appendResource(root)
       
   139     reactor.listenTCP(7080, server.Site(root))
       
   140     reactor.run()