import base64 import httplib from soaplib import client from django.test.client import Client as DjangoTestClient def Client(url, impl, username=None, password=None): """ soaplib test client url: protocol://[username:password@]host[:port]/path impl: soaplib web service description username: for basic auth password: for basic auth Usage example (with django soaplib webservice snippet) The service (app/view.py): from soaplib_handler import DjangoSoapApp, soapmethod, soap_types class HelloWorldService(DjangoSoapApp): __tns__ = 'http://my.namespace.org/soap/ @soapmethod(soap_types.String, _returns soap_types.String) def hello(who): return 'Hello %s!' hello_world_service = HelloWorldService() Your urls.py: urlpatterns = patterns( '', (r'^hello_world/', 'app.views.hello_world_service'), (r'^hello_world/service.wsdl', 'app.views.hello_world_service'), ) Accessing the web service with patched soaplib client >>> from django_soaplib_client import Client >>> cl = Client('http://localhost:8000/hello_service/', HelloWorldService()) >>> cl.hello('buddy') Hello buddy! >>> cl = Client('http://localhost:8000/hello_service/', HelloWorldService(), ... 'username', 'password') # with authentication >>> """ if username: protocol, rest = url.split('://') url = '%s://%s:%s@%s' % (protocol, username, password or '', rest) return client.make_service_client(url, impl) class FakeHTTPConnection(object): """ Replacement to root all requests to Django test client. host is something like: [username:password@]host[:port] soaplib client may not work with https. """ username = '' password = '' def __init__(self, host): """ Initializer. host:port part is ignored """ self._connection = DjangoTestClient() self._response = None if '@' in host: self.username, self.password = host.split('@')[0].split(':') def request(self, method, path, body=None, headers=None): """ Route request to Django test client. method: GET, POST, etc. path: path part of URL body: text to send to the host headers: headers dict: { header_name: (header, value), ...} """ extra = {} if headers: for key, value in headers.items(): key = 'HTTP_' + key.upper().replace('-', '_') extra[key] = value extra['REQUEST_METHOD'] = method if self.username: auth = '%s:%s' % (self.username, self.password) auth = 'Basic %s' % base64.encodestring(auth) auth = auth.strip() extra['HTTP_AUTHORIZATION'] = auth if body: resp = self._connection.post(path, body, content_type='dummy', **extra) else: resp = self._connection.get(path, **extra) self._response = resp def getresponse(self): """ Get reponse from Django. """ return FakeHTTPResponse(self._response) def close(self): """ Close request and related response object. """ if self._response: self._response.close() class FakeHTTPResponse(object): """ Replacement to get response from Django test client. """ def __init__(self, response): """ Initializer. response: Django HttpResponse object. """ self._response = response self.status = response.status_code self.reason = httplib.responses[self.status] def read(self): """ Read response body (from Django test client). """ return self._response.content def getheaders(self): """ Get response headers. """ return self._response._headers.values() class httplib_replacement: """ Replacement for monkey patching httplib. Web only need HTTPConnection. """ HTTPConnection = FakeHTTPConnection # monkey patch httlib in soaplib client with our fake class client.httplib = httplib_replacement