def help(self, method=None): "Generate sample request and response messages" (function, returns, args, doc) = self.methods[method] xml = """ <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body><%(method)s xmlns="%(namespace)s"/></soap:Body> </soap:Envelope>""" % {'method':method, 'namespace':self.namespace} request = SimpleXMLElement(xml, namespace=self.namespace, prefix=self.prefix) if args: items = args.items() elif args is None: items = [('value', None)] else: items = [] for k,v in items: request(method).marshall(k, v, add_comments=True, ns=False) xml = """ <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body><%(method)sResponse xmlns="%(namespace)s"/></soap:Body> </soap:Envelope>""" % {'method':method, 'namespace':self.namespace} response = SimpleXMLElement(xml, namespace=self.namespace, prefix=self.prefix) if returns: items = returns.items() elif args is None: items = [('value', None)] else: items = [] for k,v in items: response('%sResponse'%method).marshall(k, v, add_comments=True, ns=False) return request.as_xml(pretty=True), response.as_xml(pretty=True), doc
def call(self, method, *args, **kwargs): "Prepare xml request and make SOAP call, returning a SimpleXMLElement" #TODO: method != input_message # Basic SOAP request: xml = self.__xml % dict(method=method, namespace=self.namespace, ns=self.__ns, soap_ns=self.__soap_ns, soap_uri=soap_namespaces[self.__soap_ns]) request = SimpleXMLElement(xml, namespace=self.__ns and self.namespace, prefix=self.__ns) # serialize parameters if kwargs: parameters = kwargs.items() else: parameters = args if parameters and isinstance(parameters[0], SimpleXMLElement): # merge xmlelement parameter ("raw" - already marshalled) for param in parameters[0].children(): getattr(request, method).import_node(param) else: # marshall parameters: for k, v in parameters: # dict: tag=valor getattr(request, method).marshall(k, v) self.xml_request = request.as_xml() self.xml_response = self.send(method, self.xml_request) response = SimpleXMLElement(self.xml_response, namespace=self.namespace) if self.exceptions and response( "Fault", ns=soap_namespaces.values(), error=False): raise SoapFault(unicode(response.faultcode), unicode(response.faultstring)) return response
def call(self, method, *args, **kwargs): "Prepare xml request and make SOAP call, returning a SimpleXMLElement" # TODO: method != input_message # Basic SOAP request: xml = self.__xml % dict( method=method, namespace=self.namespace, ns=self.__ns, soap_ns=self.__soap_ns, soap_uri=soap_namespaces[self.__soap_ns], ) request = SimpleXMLElement(xml, namespace=self.__ns and self.namespace, prefix=self.__ns) # serialize parameters if kwargs: parameters = kwargs.items() else: parameters = args if parameters and isinstance(parameters[0], SimpleXMLElement): # merge xmlelement parameter ("raw" - already marshalled) for param in parameters[0].children(): getattr(request, method).import_node(param) else: # marshall parameters: for k, v in parameters: # dict: tag=valor getattr(request, method).marshall(k, v) self.xml_request = request.as_xml() self.xml_response = self.send(method, self.xml_request) response = SimpleXMLElement(self.xml_response, namespace=self.namespace) if self.exceptions and response("Fault", ns=soap_namespaces.values(), error=False): raise SoapFault(unicode(response.faultcode), unicode(response.faultstring)) return response
def call(self, method, *args, **kwargs): "Prepare xml request and make SOAP call, returning a SimpleXMLElement" #TODO: method != input_message # Basic SOAP request: if kwargs: parameters = kwargs.items() username, password = args else: (username, password), parameters = args created = datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ') expires = (datetime.utcnow() + timedelta(0, 300)).strftime('%Y-%m-%dT%H:%M:%SZ') header = self.header try: header = header % dict(Username = username, Password = password, Created=created, Expires=expires) except KeyError: pass xml = self.__xml % dict(method=method, namespace=self.namespace, ns=self.__ns, header = header, soap_ns=self.__soap_ns, soap_uri=soap_namespaces[self.__soap_ns], body_xmlns = self.body_xmlns) request = SimpleXMLElement(xml,namespace=self.__ns and self.namespace, prefix=self.__ns) # serialize parameters if parameters and isinstance(parameters[0], SimpleXMLElement): # merge xmlelement parameter ("raw" - already marshalled) for param in parameters[0].children(): getattr(request,method).import_node(param) else: # marshall parameters: for k,v in parameters: # dict: tag=valor getattr(request,method).marshall(k,v) self.xml_request = request.as_xml() try: self.xml_response = self.send(method, self.xml_request) response = SimpleXMLElement(self.xml_response, namespace=self.namespace) if self.exceptions and response("Fault", ns=soap_namespaces.values(), error=False): raise SoapFault(unicode(response.faultcode), unicode(response.faultstring)) return response except urllib2.HTTPError, error: self.xml_response = error.read() try: response = SimpleXMLElement(self.xml_response, namespace=self.namespace) except: raise error if self.exceptions and response("Fault", ns=soap_namespaces.values(), error=False): try: detail = str(response.detail.Message) except: detail = "" if "ID3242" in detail: raise NotAuthorizedError() else: raise SoapFault(unicode(response.faultcode), unicode(response.faultstring)) else: raise error
def call(self, method, *args, **kwargs): "Prepare xml request and make SOAP call, returning a SimpleXMLElement" #TODO: method != input_message # Basic SOAP request: xml = self.__xml % dict(method=method, namespace=self.namespace, ns=self.__ns, soap_ns=self.__soap_ns, soap_uri=soap_namespaces[self.__soap_ns]) request = SimpleXMLElement(xml,namespace=self.__ns and self.namespace, prefix=self.__ns) # serialize parameters if kwargs: parameters = kwargs.items() else: parameters = args if parameters and isinstance(parameters[0], SimpleXMLElement): # merge xmlelement parameter ("raw" - already marshalled) for param in parameters[0].children(): getattr(request,method).import_node(param) elif parameters: # marshall parameters: for k,v in parameters: # dict: tag=valor getattr(request,method).marshall(k,v) elif not self.__soap_server in ('oracle', ) or self.__soap_server in ('jbossas6',): # JBossAS-6 requires no empty method parameters! delattr(request("Body", ns=soap_namespaces.values(),), method) # construct header and parameters (if not wsdl given) except wsse if self.__headers and not self.services: self.__call_headers = dict([(k, v) for k, v in self.__headers.items() if not k.startswith("wsse:")]) # always extract WS Security header and send it if 'wsse:Security' in self.__headers: #TODO: namespaces too hardwired, clean-up... header = request('Header' , ns=soap_namespaces.values(),) k = 'wsse:Security' v = self.__headers[k] header.marshall(k, v, ns=False, add_children_ns=False) header(k)['xmlns:wsse'] = 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd' #<wsse:UsernameToken xmlns:wsu='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd'> if self.__call_headers: header = request('Header' , ns=soap_namespaces.values(),) for k, v in self.__call_headers.items(): ##if not self.__ns: ## header['xmlns'] header.marshall(k, v, ns=self.__ns, add_children_ns=False) self.xml_request = request.as_xml() self.xml_response = self.send(method, self.xml_request) response = SimpleXMLElement(self.xml_response, namespace=self.namespace) if self.exceptions and response("Fault", ns=soap_namespaces.values(), error=False): raise SoapFault(unicode(response.faultcode), unicode(response.faultstring)) return response
def wsdl(self): "Generate Web Service Description v1.1" xml = """<?xml version="1.0"?> <wsdl:definitions name="%(name)s" targetNamespace="%(namespace)s" xmlns:tns="%(namespace)s" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <wsdl:documentation xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">%(documentation)s</wsdl:documentation> <wsdl:types> <xsd:schema targetNamespace="%(namespace)s" elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> </xsd:schema> </wsdl:types> </wsdl:definitions> """ % { 'namespace': self.namespace, 'name': self.name, 'documentation': self.documentation } wsdl = SimpleXMLElement(xml) for method, (function, returns, args, doc) in self.methods.items(): # create elements: def parse_element(name, values, array=False, complex=False): if not complex: element = wsdl('wsdl:types')('xsd:schema').add_child( 'xsd:element') complex = element.add_child("xsd:complexType") else: complex = wsdl('wsdl:types')('xsd:schema').add_child( 'xsd:complexType') element = complex element['name'] = name if values: items = values elif values is None: items = [('value', None)] else: items = [] if not array and items: all = complex.add_child("xsd:all") elif items: all = complex.add_child("xsd:sequence") for k, v in items: e = all.add_child("xsd:element") e['name'] = k if array: e[:] = {'minOccurs': "0", 'maxOccurs': "unbounded"} if v in TYPE_MAP.keys(): t = 'xsd:%s' % TYPE_MAP[v] elif v is None: t = 'xsd:anyType' elif isinstance(v, list): n = "ArrayOf%s%s" % (name, k) l = [] for d in v: l.extend(d.items()) parse_element(n, l, array=True, complex=True) t = "tns:%s" % n elif isinstance(v, dict): n = "%s%s" % (name, k) parse_element(n, v.items(), complex=True) t = "tns:%s" % n e.add_attribute('type', t) parse_element("%s" % method, args and args.items()) parse_element("%sResponse" % method, returns and returns.items()) # create messages: for m, e in ('Input', ''), ('Output', 'Response'): message = wsdl.add_child('wsdl:message') message['name'] = "%s%s" % (method, m) part = message.add_child("wsdl:part") part[:] = { 'name': 'parameters', 'element': 'tns:%s%s' % (method, e) } # create ports portType = wsdl.add_child('wsdl:portType') portType['name'] = "%sPortType" % self.name for method, (function, returns, args, doc) in self.methods.items(): op = portType.add_child('wsdl:operation') op['name'] = method if doc: op.add_child("wsdl:documentation", doc) input = op.add_child("wsdl:input") input['message'] = "tns:%sInput" % method output = op.add_child("wsdl:output") output['message'] = "tns:%sOutput" % method # create bindings binding = wsdl.add_child('wsdl:binding') binding['name'] = "%sBinding" % self.name binding['type'] = "tns:%sPortType" % self.name soapbinding = binding.add_child('soap:binding') soapbinding['style'] = "document" soapbinding['transport'] = "http://schemas.xmlsoap.org/soap/http" for method in self.methods.keys(): op = binding.add_child('wsdl:operation') op['name'] = method soapop = op.add_child('soap:operation') soapop['soapAction'] = self.action + method soapop['style'] = 'document' input = op.add_child("wsdl:input") ##input.add_attribute('name', "%sInput" % method) soapbody = input.add_child("soap:body") soapbody["use"] = "literal" output = op.add_child("wsdl:output") ##output.add_attribute('name', "%sOutput" % method) soapbody = output.add_child("soap:body") soapbody["use"] = "literal" service = wsdl.add_child('wsdl:service') service["name"] = "%sService" % self.name service.add_child('wsdl:documentation', text=self.documentation) port = service.add_child('wsdl:port') port["name"] = "%s" % self.name port["binding"] = "tns:%sBinding" % self.name soapaddress = port.add_child('soap:address') soapaddress["location"] = self.location return wsdl.as_xml(pretty=True)
def wsdl(self): "Generate Web Service Description v1.1" xml = """<?xml version="1.0"?> <wsdl:definitions name="%(name)s" targetNamespace="%(namespace)s" xmlns:tns="%(namespace)s" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <wsdl:documentation xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">%(documentation)s</wsdl:documentation> <wsdl:types> <xsd:schema targetNamespace="%(namespace)s" elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> </xsd:schema> </wsdl:types> </wsdl:definitions> """ % {'namespace': self.namespace, 'name': self.name, 'documentation': self.documentation} wsdl = SimpleXMLElement(xml) for method, (function, returns, args, doc) in self.methods.items(): # create elements: def parse_element(name, values, array=False, complex=False): if not complex: element = wsdl('wsdl:types')('xsd:schema').add_child('xsd:element') complex = element.add_child("xsd:complexType") else: complex = wsdl('wsdl:types')('xsd:schema').add_child('xsd:complexType') element = complex element['name'] = name if values: items = values elif values is None: items = [('value', None)] else: items = [] if not array and items: all = complex.add_child("xsd:all") elif items: all = complex.add_child("xsd:sequence") for k,v in items: e = all.add_child("xsd:element") e['name'] = k if array: e[:]={'minOccurs': "0", 'maxOccurs': "unbounded"} if v in TYPE_MAP.keys(): t='xsd:%s' % TYPE_MAP[v] elif v is None: t='xsd:anyType' elif isinstance(v, list): n="ArrayOf%s%s" % (name, k) l = [] for d in v: l.extend(d.items()) parse_element(n, l, array=True, complex=True) t = "tns:%s" % n elif isinstance(v, dict): n="%s%s" % (name, k) parse_element(n, v.items(), complex=True) t = "tns:%s" % n e.add_attribute('type', t) parse_element("%s" % method, args and args.items()) parse_element("%sResponse" % method, returns and returns.items()) # create messages: for m,e in ('Input',''), ('Output','Response'): message = wsdl.add_child('wsdl:message') message['name'] = "%s%s" % (method, m) part = message.add_child("wsdl:part") part[:] = {'name': 'parameters', 'element': 'tns:%s%s' % (method,e)} # create ports portType = wsdl.add_child('wsdl:portType') portType['name'] = "%sPortType" % self.name for method, (function, returns, args, doc) in self.methods.items(): op = portType.add_child('wsdl:operation') op['name'] = method if doc: op.add_child("wsdl:documentation", doc) input = op.add_child("wsdl:input") input['message'] = "tns:%sInput" % method output = op.add_child("wsdl:output") output['message'] = "tns:%sOutput" % method # create bindings binding = wsdl.add_child('wsdl:binding') binding['name'] = "%sBinding" % self.name binding['type'] = "tns:%sPortType" % self.name soapbinding = binding.add_child('soap:binding') soapbinding['style'] = "document" soapbinding['transport'] = "http://schemas.xmlsoap.org/soap/http" for method in self.methods.keys(): op = binding.add_child('wsdl:operation') op['name'] = method soapop = op.add_child('soap:operation') soapop['soapAction'] = self.action soapop['style'] = 'document' input = op.add_child("wsdl:input") ##input.add_attribute('name', "%sInput" % method) soapbody = input.add_child("soap:body") soapbody["use"] = "literal" output = op.add_child("wsdl:output") ##output.add_attribute('name', "%sOutput" % method) soapbody = output.add_child("soap:body") soapbody["use"] = "literal" service = wsdl.add_child('wsdl:service') service["name"] = "%sService" % self.name service.add_child('wsdl:documentation', text=self.documentation) port=service.add_child('wsdl:port') port["name"] = "%s" % self.name port["binding"] = "tns:%sBinding" % self.name soapaddress = port.add_child('soap:address') soapaddress["location"] = self.location return wsdl.as_xml(pretty=True)
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)
def call(self, method, *args, **kwargs): "Prepare xml request and make SOAP call, returning a SimpleXMLElement" #TODO: method != input_message # Basic SOAP request: xml = self.__xml % dict(method=method, namespace=self.namespace, ns=self.__ns, soap_ns=self.__soap_ns, soap_uri=soap_namespaces[self.__soap_ns]) request = SimpleXMLElement(xml, namespace=self.__ns and self.namespace, prefix=self.__ns) # serialize parameters if kwargs: parameters = kwargs.items() else: parameters = args if parameters and isinstance(parameters[0], SimpleXMLElement): # merge xmlelement parameter ("raw" - already marshalled) for param in parameters[0].children(): getattr(request, method).import_node(param) elif parameters: # marshall parameters: for k, v in parameters: # dict: tag=valor getattr(request, method).marshall(k, v) elif not self.__soap_server in ('oracle', ) or self.__soap_server in ( 'jbossas6', ): # JBossAS-6 requires no empty method parameters! delattr(request( "Body", ns=soap_namespaces.values(), ), method) # construct header and parameters (if not wsdl given) except wsse if self.__headers and not self.services: self.__call_headers = dict([(k, v) for k, v in self.__headers.items() if not k.startswith("wsse:")]) # always extract WS Security header and send it if 'wsse:Security' in self.__headers: #TODO: namespaces too hardwired, clean-up... header = request( 'Header', ns=soap_namespaces.values(), ) k = 'wsse:Security' v = self.__headers[k] header.marshall(k, v, ns=False, add_children_ns=False) header( k )['xmlns:wsse'] = 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd' #<wsse:UsernameToken xmlns:wsu='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd'> if self.__call_headers: header = request( 'Header', ns=soap_namespaces.values(), ) for k, v in self.__call_headers.items(): ##if not self.__ns: ## header['xmlns'] header.marshall(k, v, ns=self.__ns, add_children_ns=False) self.xml_request = request.as_xml() self.xml_response = self.send(method, self.xml_request) response = SimpleXMLElement(self.xml_response, namespace=self.namespace) if self.exceptions and response( "Fault", ns=soap_namespaces.values(), error=False): raise SoapFault(unicode(response.faultcode), unicode(response.faultstring)) return response
def call(self, method, *args, **kwargs): "Prepare xml request and make SOAP call, returning a SimpleXMLElement" #TODO: method != input_message # Basic SOAP request: if kwargs: parameters = kwargs.items() username, password = args else: (username, password), parameters = args created = datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ') expires = (datetime.utcnow() + timedelta(0, 300)).strftime('%Y-%m-%dT%H:%M:%SZ') header = self.header try: header = header % dict(Username=username, Password=password, Created=created, Expires=expires) except KeyError: pass xml = self.__xml % dict(method=method, namespace=self.namespace, ns=self.__ns, header=header, soap_ns=self.__soap_ns, soap_uri=soap_namespaces[self.__soap_ns], body_xmlns=self.body_xmlns) request = SimpleXMLElement(xml, namespace=self.__ns and self.namespace, prefix=self.__ns) # serialize parameters if parameters and isinstance(parameters[0], SimpleXMLElement): # merge xmlelement parameter ("raw" - already marshalled) for param in parameters[0].children(): getattr(request, method).import_node(param) else: # marshall parameters: for k, v in parameters: # dict: tag=valor getattr(request, method).marshall(k, v) self.xml_request = request.as_xml() try: self.xml_response = self.send(method, self.xml_request) response = SimpleXMLElement(self.xml_response, namespace=self.namespace) if self.exceptions and response( "Fault", ns=soap_namespaces.values(), error=False): raise SoapFault(unicode(response.faultcode), unicode(response.faultstring)) return response except urllib2.HTTPError, error: self.xml_response = error.read() try: response = SimpleXMLElement(self.xml_response, namespace=self.namespace) except: raise error if self.exceptions and response( "Fault", ns=soap_namespaces.values(), error=False): try: detail = str(response.detail.Message) except: detail = "" if "ID3242" in detail: raise NotAuthorizedError() else: raise SoapFault(unicode(response.faultcode), unicode(response.faultstring)) else: raise error
def call(self, method, *args, **kwargs): """Prepare xml request and make SOAP call, returning a SimpleXMLElement. If a keyword argument called "headers" is passed with a value of a SimpleXMLElement object, then these headers will be inserted into the request. """ # TODO: method != input_message # Basic SOAP request: xml = self.__xml % dict( method=method, namespace=self.namespace, ns=self.__ns, soap_ns=self.__soap_ns, soap_uri=soap_namespaces[self.__soap_ns], ) request = SimpleXMLElement(xml, namespace=self.__ns and self.namespace, prefix=self.__ns) try: request_headers = kwargs.pop("headers") except KeyError: request_headers = None # serialize parameters if kwargs: parameters = kwargs.items() else: parameters = args if parameters and isinstance(parameters[0], SimpleXMLElement): # merge xmlelement parameter ("raw" - already marshalled) if parameters[0].children() is not None: for param in parameters[0].children(): getattr(request, method).import_node(param) elif parameters: # marshall parameters: for k, v in parameters: # dict: tag=valor getattr(request, method).marshall(k, v) elif not self.__soap_server in ("oracle",) or self.__soap_server in ("jbossas6",): # JBossAS-6 requires no empty method parameters! delattr(request("Body", ns=soap_namespaces.values()), method) # construct header and parameters (if not wsdl given) except wsse if self.__headers and not self.services: self.__call_headers = dict([(k, v) for k, v in self.__headers.items() if not k.startswith("wsse:")]) # always extract WS Security header and send it if "wsse:Security" in self.__headers: # TODO: namespaces too hardwired, clean-up... header = request("Header", ns=soap_namespaces.values()) k = "wsse:Security" v = self.__headers[k] header.marshall(k, v, ns=False, add_children_ns=False) header(k)[ "xmlns:wsse" ] = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" # <wsse:UsernameToken xmlns:wsu='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd'> if self.__call_headers: header = request("Header", ns=soap_namespaces.values()) for k, v in self.__call_headers.items(): ##if not self.__ns: ## header['xmlns'] if isinstance(v, SimpleXMLElement): # allows a SimpleXMLElement to be constructed and inserted # rather than a dictionary. marshall doesn't allow ns: prefixes # in dict key names header.import_node(v) else: header.marshall(k, v, ns=self.__ns, add_children_ns=False) if request_headers: header = request("Header", ns=soap_namespaces.values()) for subheader in request_headers.children(): header.import_node(subheader) self.xml_request = request.as_xml() self.xml_response = self.send(method, self.xml_request) response = SimpleXMLElement(self.xml_response, namespace=self.namespace, jetty=self.__soap_server in ("jetty",)) if self.exceptions and response("Fault", ns=soap_namespaces.values(), error=False): raise SoapFault(unicode(response.faultcode), unicode(response.faultstring)) return response