Changed RequestsClient to accept an underlying client

The RequestsClient uses an underlying client, by default APIClient,
to perform the request. This is important because using the previous
version of RequestsClient did not integrate well into tests which
previously relied on the django.test.client.Client behavior.

For example, making a query after making a request would fail due
to the response signal handlers closing the database connection.
This commit is contained in:
Brian Rosner 2016-11-04 16:40:49 -06:00
parent d55e176a1e
commit 3cb9d036e8
No known key found for this signature in database
GPG Key ID: A520B7186E677E82

View File

@ -47,13 +47,13 @@ if requests is not None:
A transport adapter for `requests`, that makes requests via the
Django WSGI app, rather than making actual HTTP requests over the network.
"""
def __init__(self):
def __init__(self, client):
self.app = WSGIHandler()
self.factory = DjangoRequestFactory()
self.client = client
def get_environ(self, request):
def get_raw_response(self, request):
"""
Given a `requests.PreparedRequest` instance, return a WSGI environ dict.
Given a `requests.PreparedRequest` instance, return a response from the underlying client.
"""
method = request.method
url = request.url
@ -75,7 +75,7 @@ if requests is not None:
continue
kwargs['HTTP_%s' % key.replace('-', '_')] = value
return self.factory.generic(method, url, **kwargs).environ
return self.client.generic(method, url, **kwargs)
def send(self, request, *args, **kwargs):
"""
@ -83,21 +83,17 @@ if requests is not None:
"""
raw_kwargs = {}
def start_response(wsgi_status, wsgi_headers):
status, _, reason = wsgi_status.partition(' ')
raw_kwargs['status'] = int(status)
raw_kwargs['reason'] = reason
raw_kwargs['headers'] = wsgi_headers
raw_kwargs['version'] = 11
raw_kwargs['preload_content'] = False
raw_kwargs['original_response'] = MockOriginalResponse(wsgi_headers)
# Make the outgoing request via WSGI.
environ = self.get_environ(request)
wsgi_response = self.app(environ, start_response)
raw_response = self.get_raw_response(request)
# Build the underlying urllib3.HTTPResponse
raw_kwargs['body'] = io.BytesIO(b''.join(wsgi_response))
raw_kwargs['status'] = raw_response.status_code
raw_kwargs['reason'] = raw_response.status_text
raw_kwargs['headers'] = raw_response.items()
raw_kwargs['version'] = 11
raw_kwargs['preload_content'] = False
raw_kwargs['original_response'] = MockOriginalResponse(raw_response.items())
raw_kwargs['body'] = io.BytesIO(raw_response.content)
raw = requests.packages.urllib3.HTTPResponse(**raw_kwargs)
# Build the requests.Response
@ -108,8 +104,11 @@ if requests is not None:
class RequestsClient(requests.Session):
def __init__(self, *args, **kwargs):
client = kwargs.pop("client", None)
if client is None:
client = APIClient()
super(RequestsClient, self).__init__(*args, **kwargs)
adapter = DjangoTestAdapter()
adapter = DjangoTestAdapter(client)
self.mount('http://', adapter)
self.mount('https://', adapter)