Search code examples
pythonxmlsoapsoappy

Add Header section to SOAP request using SOAPpy


I need to construct this SOAP query using python SOAPpy module:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
 <soap:Header>
  <LicenseHeader xmlns="http://schemas.acme.eu/">
   <LicenseKey>88888-88888-8888-8888-888888888888</LicenseKey>
  </LicenseHeader>
 </soap:Header>
 <soap:Body>
  <GetProductClassification xmlns="http://schemas.acme.eu/">
   <GetProductClassificationRequest />
  </GetProductClassification>
 </soap:Body>
</soap:Envelope>

So I use this code:

from SOAPpy import WSDL

wsdlFile = 'https://example.comt/1.0/service.asmx?wsdl'
server = WSDL.Proxy(wsdlFile)

result = server.GetProductClassification();

The request generated is:

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope
  SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
  xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
>
<SOAP-ENV:Body>
<GetProductClassification SOAP-ENC:root="1">
</GetProductClassification>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

When I send request I get Object reference not set to an instance of an object. I think this might be because I don't have a header section with license key in my request.

How do I modify my code to add header section with LicenseHeader parameter?


Solution

  • I am not sure how to do this in SOAPpy but I do know how to do it in suds. SUDS does the same thing as SOAPpy but it is newer and is still supported. I don't think SOAPpy is supported anymore. Below show's the code to connect to a WSDL and send a soap request:

    class MySudsClass():
    
    def sudsFunction(self):
    
        url = "http://10.10.10.10/mywsdl.wsdl"
    
        # connects to WSDL file and stores location in variable 'client'
        client = Client(url)
    
        #I have no address set in the wsdl to the camera I connect to so I set it's location here
        client.options.location = 'http:/10.10.10.11'
    
        # Create 'xml_value' object to pass as an argument using the 'factory' namespace
        xml_value = client.factory.create('some_value_in_your_xml_body')
    
        #This send the SOAP request.
        client.service.WSDLFunction(xml_value)
    

    Put this in the script before you send the soap request and it will add any headers you want.

        # Namespaces to be added to XML sent 
        wsa_ns = ('wsa', 'http://schemas.xmlsoap.org/ws/2004/08/addressing')
        wsdp_ns = ('http://schemas.xmlsoap.orf/ws/2006/02/devprof')
    
        # Field information for extra XML headers
        message = 'mymessage'
        address_txt = 'myheader_information'
    
        # Soapheaders to be added to the XML code sent
        # addPrefix allow's you to addc a extra namespace. If not needed remove it.
        message_header = Element('MessageID', ns=wsa_ns).setText(message)
        address_header = Element('Address', ns=wsa_ns).setText(address_txt).addPrefix(p='wsdp', u=wsdp_ns) 
    
        header_list = [message_header, address_header]
    
        # Soapheaders being added to suds command
        client.set_options(soapheaders=header_list)
    

    This will allow you to add in wsa encding that makes the XML understand:

        # Attribute to be added to the headers to make sure camera verifies information as correct
        mustAttribute = Attribute('SOAP-ENV:mustUnderstand', 'true')
        for x in header_list:
            x.append(mustAttribute)
    

    If you use something like this you will be able to add any headers, namespaces etc. I have used this and it worked perfectly.

    To add the license header in SUDS add:

        license_key = Element('LicenseKey', ns=some_namespace).setText('88888-88888-8888-8888-888888888888')
        license_header = Element('LicenseHeader', ns=some_namespace).insert(license_key)
    
        license_attribute = Attribute(xmlns, "http://schemas.acme.eu/")
        license_header.append(license_attribute)