1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133 | 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
|
Comments