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
    – jan-seins
    Commented Oct 2, 2018 at 17:51

3 Answers 3

31

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))
1
  • 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. Commented Oct 2, 2018 at 15:26
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
  • 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?
    – Pintun
    Commented Oct 21, 2016 at 13:42
  • 1
    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. Commented Oct 21, 2016 at 14:15
  • I have found a solution, by overriding the transport class with a local copy. Cf this question.
    – Pintun
    Commented Nov 4, 2016 at 12:46
  • 5
    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).
    – Jmons
    Commented Sep 22, 2017 at 11:45
5

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
  • 1
    Works for wcf service.
    – Max
    Commented Jan 23, 2019 at 13:55

Not the answer you're looking for? Browse other questions tagged or ask your own question.