5

I am trying to use Zeep to implement a SOAP client, as it seems the only maintained library at the moment:

  • ZSI looked very good but its latest version on pypi dates 2006
  • suds seemed to be a popular alternative, but the master is unmaintained since 2011 and there are a lot of forks out there but none seems "official" and "recent" enough to be used in a large project.

So, trying to use Zeep, I am stuck with the authentication required by the server to access the WSDL.

Such operation was quite easy with ZSI:

from ZSI.client import Binding
from ZSI.auth import AUTH

b = Binding(url='http://mysite.dom/services/MyWebServices?WSDL')
b.SetAuth(AUTH.httpbasic, 'userid', 'password')

and I can find something similar in __main__.py of Zeep:

from six.moves.urllib.parse import urlparse
from zeep.cache import InMemoryCache, SqliteCache
from zeep.client import Client
from zeep.transports import Transport

cache = SqliteCache() if args.cache else InMemoryCache()
transport_kwargs = {'cache': cache}
result = urlparse(args.wsdl_file)
if result.username or result.password:
    transport_kwargs['http_auth'] = (result.username, result.password)
transport = Transport(**transport_kwargs)
client = Client(args.wsdl_file, transport=transport)

but that does not work in my case, I get an error:

Exception: HTTPConnectionPool(host='schemas.xmlsoap.org', port=80): Max retries exceeded with url: /soap/encoding/ (Caused by NewConnectionError('<requests.packages.urllib3.connection.HTTPConnection object at 0x7f3dab9d30b8>: Failed to establish a new connection: [Errno 110] Connection timed out',))
2
  • In my case I had to send it via _soapheaders. Please checkout my answer. Commented Mar 9, 2018 at 9:41
  • @Pintun can you please change the accepted answer since the current one is outdated Commented Oct 2, 2018 at 17:51

3 Answers 3

32

Probably with the newer Version of zeep the older solution does not work anymore. Here is the new way:

from requests.auth import HTTPBasicAuth  # or HTTPDigestAuth, or OAuth1, etc.
from requests import Session
from zeep import Client
from zeep.transports import Transport

session = Session()
session.auth = HTTPBasicAuth(user, password)
client = Client('http://my-endpoint.com/production.svc?wsdl',
            transport=Transport(session=session))
Sign up to request clarification or add additional context in comments.

1 Comment

Yes, definitely this solutions works fine. The one above does not work for current version of zeep. Transport class does not accept the http_auth parameter.
10

For Basic Access Authentication you can use the HTTPBasicAuth class from the requests module, as explained on Zeep documentation http://docs.python-zeep.org/en/master/transport.html:

from requests.auth import HTTPBasicAuth  # or HTTPDigestAuth, or OAuth1, etc.
from zeep import Client
from zeep.transports import Transport

client = Client('http://my-endpoint.com/production.svc?wsdl',
    transport=Transport(http_auth=HTTPBasicAuth(user, password)))

4 Comments

Brilliant, thank you very much. I am now struggling with the fact that the WSDL, that is hosted inside an intranet, tries to import a namespace from the internet ('<import namespace="schemas.xmlsoap.org/soap/encoding/"/>'), that is not available from the client machine. Do you know if there is a way to prevent zeep client to do that?
I don't think there's an easy workaround for that. Either you modify the WSDL to make all the namespaces local (you could have for example a copy of the WSDL on the client machine, Zeep can work with that) or somehow you serve a local copy of the schema on the intranet with the corresponding URL.
I have found a solution, by overriding the transport class with a local copy. Cf this question.
Hi ya, I realise you wrote this in October last year, but I believe this has now changed: see docs.python-zeep.org/en/master/… (basically you need to do session=Session() and put the transport onto the session). But many thanks as without your answer I wouldn't have found this. (I think this is a change to Requests rather then a change to Zeep).
6

In my case the API I was working with required WS-Security (WSSE) rather than HTTP.

from zeep import Client
from zeep.wsse.username import UsernameToken

client = Client(<wsdl_url>, wsse=UsernameToken(<username>, <password>)

1 Comment

Works for wcf service.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.