Reputation: 1186
I'm trying to do simple SOAP call with WSDL and authentication, but don't know really how to pass credentials to the call. Is this possible with WSDL, or should I do this some other way?
from SOAPpy import WSDL
WSDLFILE = 'link/to/wsdl/file'
server = WSDL.Proxy(WSDLFILE)
result = server.methodCall()
Right now, I'm getting this error:
File "/usr/lib/pymodules/python2.7/SOAPpy/Client.py", line 263, in call
raise HTTPError(code, msg)
SOAPpy.Errors.HTTPError: <HTTPError 401 Unauthorized>
Upvotes: 0
Views: 1871
Reputation: 1069
Quite an old question but since it shows up first when googling "SOAPpy authentication" - I will leave my findings so maybe you won't have to bang your head for 10 hours. Giving back to community.
Googling does not provide much help but this sample here (http://code.activestate.com/recipes/444758-how-to-add-cookiesheaders-to-soappy-calls/) made me to write my own helper (version 0.0 beta)
from SOAPpy import (
WSDL,
HTTPTransport,
Config,
SOAPAddress,
)
import urllib2
import base64
class AuthenticatedTransport(HTTPTransport):
_username = None
_password = None
def call(self, addr, data, namespace, soapaction = None, encoding = None, http_proxy = None, config = Config, timeout = 10):
if not isinstance(addr, SOAPAddress):
addr = SOAPAddress(addr, config)
content_type = 'text/xml'
if encoding != None:
content_type += '; charset="%s"' % encoding
encoded_auth = None
if ( isinstance(AuthenticatedTransport._username, str) != False ):
if ( isinstance(AuthenticatedTransport._password, str) == False ):
AuthenticatedTransport._password = ""
encoded_auth = base64.b64encode('%s:%s' % (self._username, self._password))
this_request = None
if ( encoded_auth is not None ):
this_request = urllib2.Request(
url=addr.proto + "://" + addr.host + addr.path,
data=data,
headers={
"Content-Type":content_type,
"SOAPAction":"%s" % soapaction,
"Authorization":"Basic %s" % encoded_auth
}
)
else:
this_request = urllib2.Request(
url=addr.proto + "://" + addr.host + addr.path,
data=data,
headers={
"Content-Type":content_type,
"SOAPAction":"%s" % soapaction,
}
)
response = urllib2.urlopen(this_request)
data = response.read()
# get the new namespace
if namespace is None:
new_ns = None
else:
new_ns = self.getNS(namespace, data)
# return response payload
return data, new_ns
WSDL.Config.strictNamespaces = 0
username = "your_username"
password = "your_password"
WSDLFile = "https://%s:%s@some_host/your_wsdl.php?wsdl" % (username, password)
namespace = "http://futureware.biz/mantisconnect"
proxy = WSDL.Proxy(WSDLFile, namespace=namespace, transport = AuthenticatedTransport(username,password))
print(proxy.mc_get_version()) # This is my WSDL call, your will be different
For whatever reason it is not enough to use AuthenticatedTransport class, the WSDL url itself also has to contain user name and password. Maybe it's because SOAP wrapper called by WSDL here is creating separate HTTP session (remember reading about it on SOAPpy mailing list).
Hope this helps somebody.
Upvotes: 1