From 049a39e060ab8bbd028ffaa0fb2f5104a71f400d Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 17 Aug 2016 15:43:12 +0100 Subject: [PATCH] Add cookie support --- rest_framework/test.py | 41 +++++++++++++------ tests/test_requests_client.py | 76 ++++++++++++++++++++++++++++++++++- 2 files changed, 102 insertions(+), 15 deletions(-) diff --git a/rest_framework/test.py b/rest_framework/test.py index eba4b96cf..bc8ecc5db 100644 --- a/rest_framework/test.py +++ b/rest_framework/test.py @@ -26,7 +26,7 @@ def force_authenticate(request, user=None, token=None): if requests is not None: - class DjangoTestAdapter(requests.adapters.BaseAdapter): + class DjangoTestAdapter(requests.adapters.HTTPAdapter): """ A transport adapter for `requests`, that makes requests via the Django WSGI app, rather than making actual HTTP requests over the network. @@ -62,23 +62,38 @@ if requests is not None: """ Make an outgoing request to the Django WSGI application. """ - response = requests.models.Response() + raw_kwargs = {} - def start_response(status, headers): - status_code, _, reason_phrase = status.partition(' ') - response.status_code = int(status_code) - response.reason = reason_phrase - response.headers = requests.structures.CaseInsensitiveDict(headers) - response.encoding = requests.utils.get_encoding_from_headers(response.headers) + def start_response(wsgi_status, wsgi_headers): + class MockOriginalResponse(object): + def __init__(self, headers): + self.msg = requests.packages.urllib3._collections.HTTPHeaderDict(headers) + self.closed = False + def isclosed(self): + return self.closed + + def close(self): + self.closed = True + + 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) - raw_bytes = self.app(environ, start_response) + wsgi_response = self.app(environ, start_response) - response.request = request - response.url = request.url - response.raw = io.BytesIO(b''.join(raw_bytes)) + # Build the underlying urllib3.HTTPResponse + raw_kwargs['body'] = io.BytesIO(b''.join(wsgi_response)) + raw = requests.packages.urllib3.HTTPResponse(**raw_kwargs) - return response + # Build the requests.Response + return self.build_response(request, raw) def close(self): pass diff --git a/tests/test_requests_client.py b/tests/test_requests_client.py index 24e29d3b8..10158efa7 100644 --- a/tests/test_requests_client.py +++ b/tests/test_requests_client.py @@ -37,7 +37,7 @@ class Root(APIView): }) -class Headers(APIView): +class HeadersView(APIView): def get(self, request): headers = { key[5:].replace('_', '-'): value @@ -50,9 +50,32 @@ class Headers(APIView): }) +class SessionView(APIView): + def get(self, request): + return Response({ + key: value for key, value in request.session.items() + }) + + def post(self, request): + for key, value in request.data.items(): + request.session[key] = value + return Response({ + key: value for key, value in request.session.items() + }) + + +class CookiesView(APIView): + def get(self, request): + return Response({ + key: value for key, value in request.COOKIES.items() + }) + + urlpatterns = [ url(r'^$', Root.as_view()), - url(r'^headers/$', Headers.as_view()), + url(r'^headers/$', HeadersView.as_view()), + url(r'^session/$', SessionView.as_view()), + url(r'^cookies/$', CookiesView.as_view()), ] @@ -138,4 +161,53 @@ class RequestsClientTests(APITestCase): } assert response.json() == expected + def test_session(self): + response = self.requests.get('/session/') + assert response.status_code == 200 + assert response.headers['Content-Type'] == 'application/json' + expected = {} + assert response.json() == expected + + response = self.requests.post('/session/', json={'example': 'abc'}) + assert response.status_code == 200 + assert response.headers['Content-Type'] == 'application/json' + expected = {'example': 'abc'} + assert response.json() == expected + + response = self.requests.get('/session/') + assert response.status_code == 200 + assert response.headers['Content-Type'] == 'application/json' + expected = {'example': 'abc'} + assert response.json() == expected + + def test_cookies(self): + """ + Test for explicitly setting a cookie. + """ + my_cookie = { + "version": 0, + "name": 'COOKIE_NAME', + "value": 'COOKIE_VALUE', + "port": None, + # "port_specified":False, + "domain": 'testserver.local', + # "domain_specified":False, + # "domain_initial_dot":False, + "path": '/', + # "path_specified":True, + "secure": False, + "expires": None, + "discard": True, + "comment": None, + "comment_url": None, + "rest": {}, + "rfc2109": False + } + self.requests.cookies.set(**my_cookie) + response = self.requests.get('/cookies/') + assert response.status_code == 200 + assert response.headers['Content-Type'] == 'application/json' + expected = {'COOKIE_NAME': 'COOKIE_VALUE'} + assert response.json() == expected + # cookies/session auth