Python - Zeep SOAP Complex Header

CaramuchoDotCom picture CaramuchoDotCom · Mar 22, 2017 · Viewed 10.8k times · Source

I'd like to pass "Complex" Header to a SOAP service with zeep library

Here's what it should look like

 <soapenv:Header>
      <something:myVar1>FOO</something:myVar1>
      <something:myVar2>JAM</something:myVar2>
 </soapenv:Header>

I guess that I succeed in sending a header this way

header = xsd.Element(
    '{http://urlofthews}Header',
        xsd.ComplexType([
        xsd.Element(
        '{http://urlofthews}myVar1',
        xsd.String()),
        xsd.Element(
        '{http://urlofthews}myVar2',
        xsd.String())
        ])
    )

header_value = header(myVar1='FOO',myVar2='JAM')
print (header_value)
datasoap=client.service.UserRessourcesCatalog(requete,_soapheaders=[header_value])

But I don't get how to declare and pass the namespace "something" in my Header with the XSD.

Any Help ?

Thx by advance.

Best Regards


As mentionned in the documentation

http://docs.python-zeep.org/en/master/headers.html

"Another option is to pass an lxml Element object. This is generally useful if the wsdl doesn’t define a soap header but the server does expect it."

which is my case so I tried

try:
        import xml.etree.cElementTree as ET
    except ImportError:
        import xml.etree.ElementTree as ET
    ET.register_namespace('something', 'http://urlofthews')

    headerXML = ET.Element("soapenv:Header")
    var1 = ET.SubElement(headerXML, "something:myVar1")
    var1.text = "FOO"
    var2 = ET.SubElement(headerXML, "something:myVar2")
    var2.text = "JAM"


headerDict=xmltodict.parse(ET.tostring(headerXML))
print (json.dumps(headerDict))

    datasoap=client.service.UserRessourcesCatalog(requete,_soapheaders=headerDict)

But I get : ComplexType() got an unexpected keyword argument u'soapenv:Header'. Signature: ``

Answer

oblivion02 picture oblivion02 · Jun 28, 2017

I recently encountered this problem, and here is how I solved it.

Say you have a 'Security' header that looks as follows...

<env:Header>
<Security>
    <UsernameToken>
        <Username>__USERNAME__</Username>
        <Password>__PWD__</Password>
    </UsernameToken>
    <ServiceAccessToken>        
        <AccessLicenseNumber>__KEY__</AccessLicenseNumber>
    </ServiceAccessToken>
</Security>
</env:Header>

In order to send this header in the zeep client's request, you would need to do the following:

header = zeep.xsd.Element(
            'Security',
            zeep.xsd.ComplexType([
                zeep.xsd.Element(
                    'UsernameToken',
                    zeep.xsd.ComplexType([
                        zeep.xsd.Element('Username',zeep.xsd.String()),
                        zeep.xsd.Element('Password',zeep.xsd.String()),
                    ])
                ),
                zeep.xsd.Element(
                    'ServiceAccessToken',
                    zeep.xsd.ComplexType([
                        zeep.xsd.Element('AccessLicenseNumber',zeep.xsd.String()),
                    ])
                ),
            ])
        )

header_value = header(UsernameToken={'Username':'test_user','Password':'testing'},UPSServiceAccessToken={'AccessLicenseNumber':'test_pwd'})

client.service.method_name_goes_here(
                    _soapheaders=[header_value],#other method data goes here
                )