1

I can't seem to get SUDS to download a WSDL that requires Basic auth credentials. My code is simple:

wsdl_url = 'https://example.com/ChangeRequest.do?WSDL'
self.client = Client(wsdl_url, username=username, password=password)

I've also tried:

from suds.transport.https import HttpAuthenticated

wsdl_url = 'https://example.com/ChangeRequest.do?WSDL'
credentials = dict(username=username, password=password)
t = HttpAuthenticated(**credentials)
self.client = Client(url=wsdl_url, transport=t)

In both cases, the service returns a 403 Forbidden error. I can go down into the SUDS code in http.py and add this line to the call:

u2request.add_header('Authorization','Basic xxxxxxxxxxxxxxxxxxxx')

This works. What am I doing wrong to get SUDS to pass my credentials when downloading the WSDL?

Note: I try to connect to the WSDL directly using both Chrome's Postman plugin and SoapUI, and the service works as well. So I know the credentials are correct.

Ryan Nelson
  • 4,466
  • 5
  • 29
  • 45
  • Have you tried the answer from here?: http://stackoverflow.com/questions/11742494/python-soap-client-wsdl-call-with-suds-gives-transport-error-401-unauthorized-f – German Petrov Sep 08 '14 at 15:15

2 Answers2

1

I encountered a similar issue (suds v0.4, wsdl, 403), and found out that it was because the server I'm trying to access blocks any requests with the header User-Agent set like Python-urllib* (suds is using urllib2, hence the default header). Explicitly change the header solves the issue.

Particular to my solution: I overrode the open method of a transport class, and set client options, like the following code snippet. Note that we need to explicitly set for open and subsequent requests separately. Please advice better ways to circumvent this if you know any. And hope this post could help save someone's time in the future.

import urllib2
import suds
from suds.transport.https import HttpAuthenticated
from suds.transport import TransportError

URL = 'https://example.com/ChangeRequest.do?WSDL'

class HttpHeaderModify(HttpAuthenticated):
    def open(self, request):
        try:
            url = request.url
            u2request = urllib2.Request(url, headers={'User-Agent': 'Mozilla'})
            self.proxy = self.options.proxy
            return self.u2open(u2request)
        except urllib2.HTTPError, e:
            raise TransportError(str(e), e.code, e.fp)

transport = HttpHeaderModify()
client = Client(URL, transport=transport, timeout=10)

# Subsequent requests' header needs to be set again here. The overridden transport
# class only handles opening of the client.
client.set_options(headers={'User-Agent': 'Mozilla'})

P.S. Though my problem may not be the same, searching for "403 suds" pops up this SO question, so I decide just post my solution here.

reference post that gave me the right direction: https://bitbucket.org/jurko/suds/issues/27/client-request-for-wsdl-does-not-use-given

suheti
  • 103
  • 1
  • 5
0

I used to have this issue before and compare with the soap UI header. Found that suds missing to include the header (Host).

client.set_options(headers={'Host': 'value'})

And issue fixed.

Heimax
  • 1