Reputation: 91
I'd like to pass "Complex" Header to a SOAP service using the 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 how can I declare and pass the namespace "something" in my Header
with the XSD?
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: ``
Upvotes: 7
Views: 14541
Reputation: 314
It's an old question, but there are lots of related issues for setting soap headers with zeep. The docs says there is four ways to do it, but does not give example for the last one, so here is one.
It is better than the raw call because you still use zeep for the body and soap itself.
It is simpler than declaring the complete xsd structure.
from zeep import Client
from lxml import etree
headers = etree.XML('<Header><Token xmlns="http://www.example.com/objets/Authentification/1.0">'+result["Token"]+'</Token></Header>')
client = Client("https://www.example.com/services/ServiceName/4.2/Service.svc?singleWsdl")
result = client.service.MethodeName(
payload,
_soapheaders=[*headers],
)
Upvotes: 0
Reputation: 1
From a related question:
Bearer Token authorization header in SOAP client with Zeep and Python
import requests
from zeep import Client, Transport
headers = {
"Authorization": "Bearer " + get_token()
}
session = requests.Session()
session.headers.update(headers)
transport = Transport(session=session)
client = Client(wsdl=url, transport=transport)
Upvotes: -1
Reputation: 91
Thx Oblivion02.
I finally use a raw method
headers = {'content-type': 'text/xml'}
body = """<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:web="http://blablabla">
<soapenv:Header>
<something:myVar1>FOO</something:myVar1>
<something:myVar2>JAM</something:myVar2>
</soapenv:Header>
<soapenv:Body>
...
</soapenv:Body>
</soapenv:Envelope>"""
response = requests.post(wsdl,data=body,headers=headers)
Upvotes: 2
Reputation: 567
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
)
Upvotes: 31