def dispatch(self, xml, action=None):
        "Receive and proccess SOAP call"
        # default values:
        prefix = self.prefix
        ret = fault = None
        soap_ns, soap_uri = self.soap_ns, self.soap_uri
        soap_fault_code = 'VersionMismatch'
        name = None

        try:
            request = SimpleXMLElement(xml, namespace=self.namespace)

            # detect soap prefix and uri (xmlns attributes of Envelope)
            for k, v in request[:]:
                if v in ("http://schemas.xmlsoap.org/soap/envelope/",
                                  "http://www.w3.org/2003/05/soap-env",):
                    soap_ns = request.attributes()[k].localName
                    soap_uri = request.attributes()[k].value
            
            soap_fault_code = 'Client'
            
            # parse request message and get local method            
            method = request('Body', ns=soap_uri).children()(0)
            if action:
                # method name = action 
                name = action[len(self.action)+1:-1]
                prefix = self.prefix
            if not action or not name:
                # method name = input message name
                name = method.get_local_name()
                prefix = method.get_prefix()

            log.debug('dispatch method %s', name)
            function, returns_types, args_types, doc = self.methods[name]
        
            # de-serialize parameters (if type definitions given)
            if args_types:
                args = method.children().unmarshall(args_types)
            elif args_types is None:
                args = {'request':method} # send raw request
            else:
                args = {} # no parameters
 
            soap_fault_code = 'Server'
            # execute function
            ret = function(**args)
            log.debug('%s', ret)

        except Exception, e:
            import sys
            etype, evalue, etb = sys.exc_info()
            if DEBUG: 
                import traceback
                detail = ''.join(traceback.format_exception(etype, evalue, etb))
                detail += '\n\nXML REQUEST\n\n' + xml
            else:
                detail = None
            fault = {'faultcode': "%s.%s" % (soap_fault_code, etype.__name__), 
                     'faultstring': unicode(evalue), 
                     'detail': detail}
    def dispatch(self, xml):
        "Receive and proccess SOAP call"
        # default values:
        prefix = self.prefix
        ret = fault = None
        soap_ns, soap_uri = self.soap_ns, self.soap_uri
        soap_fault_code = 'VersionMismatch'

        try:
            request = SimpleXMLElement(xml, namespace=self.namespace)

            # detect soap prefix and uri (xmlns attributes of Envelope)
            for k, v in request[:]:
                if v in (
                        "http://schemas.xmlsoap.org/soap/envelope/",
                        "http://www.w3.org/2003/05/soap-env",
                ):
                    soap_ns = request.attributes()[k].localName
                    soap_uri = request.attributes()[k].value

            soap_fault_code = 'Client'

            # parse request message and get local method
            method = request('Body', ns=soap_uri).children()(0)
            name = method.get_local_name()
            prefix = method.get_prefix()
            if DEBUG: print "dispatch method", name
            function, returns_types, args_types, doc = self.methods[name]

            # de-serialize parameters (if type definitions given)
            if args_types:
                args = method.children().unmarshall(args_types)
            elif args_types is None:
                args = {'request': method}  # send raw request
            else:
                args = {}  # no parameters

            soap_fault_code = 'Server'
            # execute function
            ret = function(**args)
            if DEBUG: print ret

        except Exception, e:
            import sys
            etype, evalue, etb = sys.exc_info()
            if DEBUG:
                import traceback
                detail = ''.join(traceback.format_exception(
                    etype, evalue, etb))
                detail += '\n\nXML REQUEST\n\n' + xml
            else:
                detail = None
            fault = {
                'faultcode': "%s.%s" % (soap_fault_code, etype.__name__),
                'faultstring': unicode(evalue),
                'detail': detail
            }
示例#3
0
文件: server.py 项目: 2089764/web2py
    def dispatch(self, xml, action=None):
        "Receive and proccess SOAP call"
        # default values:
        prefix = self.prefix
        ret = fault = None
        soap_ns, soap_uri = self.soap_ns, self.soap_uri
        soap_fault_code = 'VersionMismatch'
        name = None
        
        # namespaces = [('model', 'http://model.common.mt.moboperator'), ('external', 'http://external.mt.moboperator')]
        _ns_reversed = dict(((v,k) for k,v in self.namespaces.iteritems())) # Switch keys-values
        # _ns_reversed = {'http://external.mt.moboperator': 'external', 'http://model.common.mt.moboperator': 'model'}
        
        try:
            request = SimpleXMLElement(xml, namespace=self.namespace)
            
            # detect soap prefix and uri (xmlns attributes of Envelope)
            for k, v in request[:]:
                if v in ("http://schemas.xmlsoap.org/soap/envelope/",
                                  "http://www.w3.org/2003/05/soap-env",):
                    soap_ns = request.attributes()[k].localName
                    soap_uri = request.attributes()[k].value
                
                # If the value from attributes on Envelope is in additional namespaces
                elif v in self.namespaces.values():
                    _ns = request.attributes()[k].localName
                    _uri = request.attributes()[k].value
                    _ns_reversed[_uri] = _ns # update with received alias
                    # Now we change 'external' and 'model' to the received forms i.e. 'ext' and 'mod'
                # After that we know how the client has prefixed additional namespaces
            
            ns = NS_RX.findall(xml)
            for k, v in ns:
                if v in self.namespaces.values():
                    _ns_reversed[v] = k
            
            soap_fault_code = 'Client'
            
            # parse request message and get local method
            method = request('Body', ns=soap_uri).children()(0)
            if action:
                # method name = action 
                name = action[len(self.action)+1:-1]
                prefix = self.prefix
            if not action or not name:
                # method name = input message name
                name = method.get_local_name()
                prefix = method.get_prefix()

            log.debug('dispatch method: %s', name)
            function, returns_types, args_types, doc = self.methods[name]
            log.debug('returns_types %s', returns_types)
            
            # de-serialize parameters (if type definitions given)
            if args_types:
                args = method.children().unmarshall(args_types)
            elif args_types is None:
                args = {'request': method} # send raw request
            else:
                args = {} # no parameters
            
            soap_fault_code = 'Server'
            # execute function
            ret = function(**args)
            log.debug('dispathed method returns: %s', ret)

        except Exception: # This shouldn't be one huge try/except
            import sys
            etype, evalue, etb = sys.exc_info()
            log.error(traceback.format_exc())
            if self.debug:
                detail = ''.join(traceback.format_exception(etype, evalue, etb))
                detail += '\n\nXML REQUEST\n\n' + xml
            else:
                detail = None
            fault = {'faultcode': "%s.%s" % (soap_fault_code, etype.__name__), 
                     'faultstring': unicode(evalue), 
                     'detail': detail}

        # build response message
        if not prefix:
            xml = """<%(soap_ns)s:Envelope xmlns:%(soap_ns)s="%(soap_uri)s"/>"""  
        else:
            xml = """<%(soap_ns)s:Envelope xmlns:%(soap_ns)s="%(soap_uri)s"
                       xmlns:%(prefix)s="%(namespace)s"/>"""  
            
        xml %= {    # a %= {} is a shortcut for a = a % {}
            'namespace': self.namespace, 
            'prefix': prefix,
            'soap_ns': soap_ns, 
            'soap_uri': soap_uri
        }
        
        # Now we add extra namespaces
        xml = SoapDispatcher._extra_namespaces(xml, _ns_reversed)
        
        # Change our namespace alias to that given by the client.
        # We put [('model', 'http://model.common.mt.moboperator'), ('external', 'http://external.mt.moboperator')]
        # mix it with {'http://external.mt.moboperator': 'ext', 'http://model.common.mt.moboperator': 'mod'}
        mapping = dict(((k, _ns_reversed[v]) for k,v in self.namespaces.iteritems())) # Switch keys-values and change value
        # and get {'model': u'mod', 'external': u'ext'}
        
        response = SimpleXMLElement(xml, 
                                    namespace=self.namespace,
                                    namespaces_map = mapping,
                                    prefix=prefix)
        
        response['xmlns:xsi'] = "http://www.w3.org/2001/XMLSchema-instance"
        response['xmlns:xsd'] = "http://www.w3.org/2001/XMLSchema"
        
        body = response.add_child("%s:Body" % soap_ns, ns=False)
        
        if fault:
            # generate a Soap Fault (with the python exception)
            body.marshall("%s:Fault" % soap_ns, fault, ns=False)
        else:
            # return normal value
            res = body.add_child("%sResponse" % name, ns=prefix)
            if not prefix:
                res['xmlns'] = self.namespace # add target namespace

            # serialize returned values (response) if type definition available
            if returns_types:
                if not isinstance(ret, dict):
                    res.marshall(returns_types.keys()[0], ret, )
                else:
                    for k,v in ret.items():
                        res.marshall(k, v)
            elif returns_types is None:
                # merge xmlelement returned
                res.import_node(ret)
            elif returns_types == {}:
                log.warning('Given returns_types is an empty dict.')

        return response.as_xml(pretty=self.pretty)
示例#4
0
    def dispatch(self, xml, action=None):
        """Receive and process SOAP call"""
        # default values:
        prefix = self.prefix
        ret = fault = None
        soap_ns, soap_uri = self.soap_ns, self.soap_uri
        soap_fault_code = 'VersionMismatch'
        name = None

        # namespaces = [('model', 'http://model.common.mt.moboperator'), ('external', 'http://external.mt.moboperator')]
        _ns_reversed = dict(
            ((v, k)
             for k, v in self.namespaces.iteritems()))  # Switch keys-values
        # _ns_reversed = {'http://external.mt.moboperator': 'external', 'http://model.common.mt.moboperator': 'model'}

        try:
            request = SimpleXMLElement(xml, namespace=self.namespace)

            # detect soap prefix and uri (xmlns attributes of Envelope)
            for k, v in request[:]:
                if v in (
                        "http://schemas.xmlsoap.org/soap/envelope/",
                        "http://www.w3.org/2003/05/soap-env",
                ):
                    soap_ns = request.attributes()[k].localName
                    soap_uri = request.attributes()[k].value

                # If the value from attributes on Envelope is in additional namespaces
                elif v in self.namespaces.values():
                    _ns = request.attributes()[k].localName
                    _uri = request.attributes()[k].value
                    _ns_reversed[_uri] = _ns  # update with received alias
                    # Now we change 'external' and 'model' to the received forms i.e. 'ext' and 'mod'
                # After that we know how the client has prefixed additional namespaces

            ns = NS_RX.findall(xml)
            for k, v in ns:
                if v in self.namespaces.values():
                    _ns_reversed[v] = k

            soap_fault_code = 'Client'

            # parse request message and get local method
            method = request('Body', ns=soap_uri).children()(0)
            if action:
                # method name = action
                name = action[len(self.action) + 1:-1]
                prefix = self.prefix
            if not action or not name:
                # method name = input message name
                name = method.get_local_name()
                prefix = method.get_prefix()

            log.debug('dispatch method: %s', name)
            function, returns_types, args_types, doc = self.methods[name]
            log.debug('returns_types %s', returns_types)

            # de-serialize parameters (if type definitions given)
            if args_types:
                args = method.children().unmarshall(args_types)
            elif args_types is None:
                args = {'request': method}  # send raw request
            else:
                args = {}  # no parameters

            soap_fault_code = 'Server'
            # execute function
            ret = function(**args)
            log.debug('dispathed method returns: %s', ret)

        except Exception:  # This shouldn't be one huge try/except
            import sys
            etype, evalue, etb = sys.exc_info()
            log.error(traceback.format_exc())
            if self.debug:
                detail = ''.join(traceback.format_exception(
                    etype, evalue, etb))
                detail += '\n\nXML REQUEST\n\n' + xml
            else:
                detail = None
            fault = {
                'faultcode': "%s.%s" % (soap_fault_code, etype.__name__),
                'faultstring': unicode(evalue),
                'detail': detail
            }

        # build response message
        if not prefix:
            xml = """<%(soap_ns)s:Envelope xmlns:%(soap_ns)s="%(soap_uri)s"/>"""
        else:
            xml = """<%(soap_ns)s:Envelope xmlns:%(soap_ns)s="%(soap_uri)s"
                       xmlns:%(prefix)s="%(namespace)s"/>"""

        xml %= {  # a %= {} is a shortcut for a = a % {}
            'namespace': self.namespace,
            'prefix': prefix,
            'soap_ns': soap_ns,
            'soap_uri': soap_uri
        }

        # Now we add extra namespaces
        xml = SoapDispatcher._extra_namespaces(xml, _ns_reversed)

        # Change our namespace alias to that given by the client.
        # We put [('model', 'http://model.common.mt.moboperator'), ('external', 'http://external.mt.moboperator')]
        # mix it with {'http://external.mt.moboperator': 'ext', 'http://model.common.mt.moboperator': 'mod'}
        mapping = dict(
            ((k, _ns_reversed[v]) for k, v in self.namespaces.iteritems()
             ))  # Switch keys-values and change value
        # and get {'model': u'mod', 'external': u'ext'}

        response = SimpleXMLElement(xml,
                                    namespace=self.namespace,
                                    namespaces_map=mapping,
                                    prefix=prefix)

        response['xmlns:xsi'] = "http://www.w3.org/2001/XMLSchema-instance"
        response['xmlns:xsd'] = "http://www.w3.org/2001/XMLSchema"

        body = response.add_child("%s:Body" % soap_ns, ns=False)

        if fault:
            # generate a Soap Fault (with the python exception)
            body.marshall("%s:Fault" % soap_ns, fault, ns=False)
        else:
            # return normal value
            res = body.add_child("%sResponse" % name, ns=prefix)
            if not prefix:
                res['xmlns'] = self.namespace  # add target namespace

            # serialize returned values (response) if type definition available
            if returns_types:
                if not isinstance(ret, dict):
                    res.marshall(
                        returns_types.keys()[0],
                        ret,
                    )
                else:
                    for k, v in ret.items():
                        res.marshall(k, v)
            elif returns_types is None:
                # merge xmlelement returned
                res.import_node(ret)
            elif returns_types == {}:
                log.warning('Given returns_types is an empty dict.')

        return response.as_xml(pretty=self.pretty)