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 }
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)
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)