From 3cb9d036e8e156c7712906286beeb0053901d071 Mon Sep 17 00:00:00 2001 From: Brian Rosner Date: Fri, 4 Nov 2016 16:40:49 -0600 Subject: [PATCH] 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. --- rest_framework/test.py | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/rest_framework/test.py b/rest_framework/test.py index 241f94c91..e28a95971 100644 --- a/rest_framework/test.py +++ b/rest_framework/test.py @@ -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)