Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Fixed #21341 -- Eased https requests with the test client

All request methods of ``django.test.client.Client`` receive a ``secure``
argument that defaults to ``False`` indicating whether or not to make the
request through https.
Thanks Aymeric Augustin for the review.
  • Loading branch information...
commit 99b681e227b5b7880d6edd0d8dd670034d431859 1 parent 19256f3
@unaizalakain unaizalakain authored claudep committed
View
82 django/test/client.py
@@ -269,60 +269,68 @@ def _get_path(self, parsed):
path = path.encode('utf-8').decode('iso-8859-1')
return path
- def get(self, path, data={}, **extra):
+ def get(self, path, data={}, secure=False, **extra):
"Construct a GET request."
r = {
'QUERY_STRING': urlencode(data, doseq=True),
}
r.update(extra)
- return self.generic('GET', path, **r)
+ return self.generic('GET', path, secure=secure, **r)
def post(self, path, data={}, content_type=MULTIPART_CONTENT,
- **extra):
+ secure=False, **extra):
"Construct a POST request."
post_data = self._encode_data(data, content_type)
- return self.generic('POST', path, post_data, content_type, **extra)
+ return self.generic('POST', path, post_data, content_type,
+ secure=secure, **extra)
- def head(self, path, data={}, **extra):
+ def head(self, path, data={}, secure=False, **extra):
"Construct a HEAD request."
r = {
'QUERY_STRING': urlencode(data, doseq=True),
}
r.update(extra)
- return self.generic('HEAD', path, **r)
+ return self.generic('HEAD', path, secure=secure, **r)
def options(self, path, data='', content_type='application/octet-stream',
- **extra):
+ secure=False, **extra):
"Construct an OPTIONS request."
- return self.generic('OPTIONS', path, data, content_type, **extra)
+ return self.generic('OPTIONS', path, data, content_type,
+ secure=secure, **extra)
def put(self, path, data='', content_type='application/octet-stream',
- **extra):
+ secure=False, **extra):
"Construct a PUT request."
- return self.generic('PUT', path, data, content_type, **extra)
+ return self.generic('PUT', path, data, content_type,
+ secure=secure, **extra)
def patch(self, path, data='', content_type='application/octet-stream',
- **extra):
+ secure=False, **extra):
"Construct a PATCH request."
- return self.generic('PATCH', path, data, content_type, **extra)
+ return self.generic('PATCH', path, data, content_type,
+ secure=secure, **extra)
def delete(self, path, data='', content_type='application/octet-stream',
- **extra):
+ secure=False, **extra):
"Construct a DELETE request."
- return self.generic('DELETE', path, data, content_type, **extra)
+ return self.generic('DELETE', path, data, content_type,
+ secure=secure, **extra)
- def generic(self, method, path,
- data='', content_type='application/octet-stream', **extra):
+ def generic(self, method, path, data='',
+ content_type='application/octet-stream', secure=False,
+ **extra):
"""Constructs an arbitrary HTTP request."""
parsed = urlparse(path)
data = force_bytes(data, settings.DEFAULT_CHARSET)
r = {
'PATH_INFO': self._get_path(parsed),
'REQUEST_METHOD': str(method),
+ 'SERVER_PORT': str('443') if secure else str('80'),
+ 'wsgi.url_scheme': str('https') if secure else str('http'),
}
if data:
r.update({
@@ -445,72 +453,82 @@ def request(self, **request):
signals.template_rendered.disconnect(dispatch_uid=signal_uid)
got_request_exception.disconnect(dispatch_uid="request-exception")
- def get(self, path, data={}, follow=False, **extra):
+ def get(self, path, data={}, follow=False, secure=False, **extra):
"""
Requests a response from the server using GET.
"""
- response = super(Client, self).get(path, data=data, **extra)
+ response = super(Client, self).get(path, data=data, secure=secure,
+ **extra)
if follow:
response = self._handle_redirects(response, **extra)
return response
def post(self, path, data={}, content_type=MULTIPART_CONTENT,
- follow=False, **extra):
+ follow=False, secure=False, **extra):
"""
Requests a response from the server using POST.
"""
- response = super(Client, self).post(path, data=data, content_type=content_type, **extra)
+ response = super(Client, self).post(path, data=data,
+ content_type=content_type,
+ secure=secure, **extra)
if follow:
response = self._handle_redirects(response, **extra)
return response
- def head(self, path, data={}, follow=False, **extra):
+ def head(self, path, data={}, follow=False, secure=False, **extra):
"""
Request a response from the server using HEAD.
"""
- response = super(Client, self).head(path, data=data, **extra)
+ response = super(Client, self).head(path, data=data, secure=secure,
+ **extra)
if follow:
response = self._handle_redirects(response, **extra)
return response
def options(self, path, data='', content_type='application/octet-stream',
- follow=False, **extra):
+ follow=False, secure=False, **extra):
"""
Request a response from the server using OPTIONS.
"""
- response = super(Client, self).options(path, data=data, content_type=content_type, **extra)
+ response = super(Client, self).options(path, data=data,
+ content_type=content_type,
+ secure=secure, **extra)
if follow:
response = self._handle_redirects(response, **extra)
return response
def put(self, path, data='', content_type='application/octet-stream',
- follow=False, **extra):
+ follow=False, secure=False, **extra):
"""
Send a resource to the server using PUT.
"""
- response = super(Client, self).put(path, data=data, content_type=content_type, **extra)
+ response = super(Client, self).put(path, data=data,
+ content_type=content_type,
+ secure=secure, **extra)
if follow:
response = self._handle_redirects(response, **extra)
return response
def patch(self, path, data='', content_type='application/octet-stream',
- follow=False, **extra):
+ follow=False, secure=False, **extra):
"""
Send a resource to the server using PATCH.
"""
- response = super(Client, self).patch(
- path, data=data, content_type=content_type, **extra)
+ response = super(Client, self).patch(path, data=data,
+ content_type=content_type,
+ secure=secure, **extra)
if follow:
response = self._handle_redirects(response, **extra)
return response
def delete(self, path, data='', content_type='application/octet-stream',
- follow=False, **extra):
+ follow=False, secure=False, **extra):
"""
Send a DELETE request to the server.
"""
- response = super(Client, self).delete(
- path, data=data, content_type=content_type, **extra)
+ response = super(Client, self).delete(path, data=data,
+ content_type=content_type,
+ secure=secure, **extra)
if follow:
response = self._handle_redirects(response, **extra)
return response
View
4 docs/releases/1.7.txt
@@ -444,6 +444,10 @@ Tests
client can't fetch externals URLs, this allows you to use ``assertRedirects``
with redirects that aren't part of your Django app.
+* The ``secure`` argument was added to all the request methods of
+ :class:`~django.test.Client`. If ``True``, the request will be made
+ through HTTPS.
+
Backwards incompatible changes in 1.7
=====================================
View
35 docs/topics/testing/overview.txt
@@ -431,8 +431,11 @@ Use the ``django.test.Client`` class to make requests.
Once you have a ``Client`` instance, you can call any of the following
methods:
- .. method:: Client.get(path, data={}, follow=False, **extra)
+ .. method:: Client.get(path, data={}, follow=False, secure=False, **extra)
+ .. versionadded:: 1.7
+
+ The ``secure`` argument was added.
Makes a GET request on the provided ``path`` and returns a ``Response``
object, which is documented below.
@@ -488,7 +491,10 @@ Use the ``django.test.Client`` class to make requests.
>>> response.redirect_chain
[(u'http://testserver/next/', 302), (u'http://testserver/final/', 302)]
- .. method:: Client.post(path, data={}, content_type=MULTIPART_CONTENT, follow=False, **extra)
+ If you set ``secure`` to ``True`` the client will emulate an HTTPS
+ request.
+
+ .. method:: Client.post(path, data={}, content_type=MULTIPART_CONTENT, follow=False, secure=False, **extra)
Makes a POST request on the provided ``path`` and returns a
``Response`` object, which is documented below.
@@ -562,14 +568,17 @@ Use the ``django.test.Client`` class to make requests.
and a ``redirect_chain`` attribute will be set in the response object
containing tuples of the intermediate urls and status codes.
- .. method:: Client.head(path, data={}, follow=False, **extra)
+ If you set ``secure`` to ``True`` the client will emulate an HTTPS
+ request.
+
+ .. method:: Client.head(path, data={}, follow=False, secure=False, **extra)
Makes a HEAD request on the provided ``path`` and returns a
``Response`` object. This method works just like :meth:`Client.get`,
- including the ``follow`` and ``extra`` arguments, except it does not
- return a message body.
+ including the ``follow``, ``secure`` and ``extra`` arguments, except
+ it does not return a message body.
- .. method:: Client.options(path, data='', content_type='application/octet-stream', follow=False, **extra)
+ .. method:: Client.options(path, data='', content_type='application/octet-stream', follow=False, secure=False, **extra)
Makes an OPTIONS request on the provided ``path`` and returns a
``Response`` object. Useful for testing RESTful interfaces.
@@ -577,10 +586,10 @@ Use the ``django.test.Client`` class to make requests.
When ``data`` is provided, it is used as the request body, and
a ``Content-Type`` header is set to ``content_type``.
- The ``follow`` and ``extra`` arguments act the same as for
+ The ``follow``, ``secure`` and ``extra`` arguments act the same as for
:meth:`Client.get`.
- .. method:: Client.put(path, data='', content_type='application/octet-stream', follow=False, **extra)
+ .. method:: Client.put(path, data='', content_type='application/octet-stream', follow=False, secure=False, **extra)
Makes a PUT request on the provided ``path`` and returns a
``Response`` object. Useful for testing RESTful interfaces.
@@ -588,18 +597,18 @@ Use the ``django.test.Client`` class to make requests.
When ``data`` is provided, it is used as the request body, and
a ``Content-Type`` header is set to ``content_type``.
- The ``follow`` and ``extra`` arguments act the same as for
+ The ``follow``, ``secure`` and ``extra`` arguments act the same as for
:meth:`Client.get`.
- .. method:: Client.patch(path, data='', content_type='application/octet-stream', follow=False, **extra)
+ .. method:: Client.patch(path, data='', content_type='application/octet-stream', follow=False, secure=False, **extra)
Makes a PATCH request on the provided ``path`` and returns a
``Response`` object. Useful for testing RESTful interfaces.
- The ``follow`` and ``extra`` arguments act the same as for
+ The ``follow``, ``secure`` and ``extra`` arguments act the same as for
:meth:`Client.get`.
- .. method:: Client.delete(path, data='', content_type='application/octet-stream', follow=False, **extra)
+ .. method:: Client.delete(path, data='', content_type='application/octet-stream', follow=False, secure=False, **extra)
Makes an DELETE request on the provided ``path`` and returns a
``Response`` object. Useful for testing RESTful interfaces.
@@ -607,7 +616,7 @@ Use the ``django.test.Client`` class to make requests.
When ``data`` is provided, it is used as the request body, and
a ``Content-Type`` header is set to ``content_type``.
- The ``follow`` and ``extra`` arguments act the same as for
+ The ``follow``, ``secure`` and ``extra`` arguments act the same as for
:meth:`Client.get`.
.. method:: Client.login(**credentials)
View
12 tests/test_client/tests.py
@@ -93,6 +93,18 @@ def test_raw_post(self):
self.assertEqual(response.templates[0].name, "Book template")
self.assertEqual(response.content, b"Blink - Malcolm Gladwell")
+ def test_insecure(self):
+ "GET a URL through http"
+ response = self.client.get('/test_client/secure_view/', secure=False)
+ self.assertFalse(response.test_was_secure_request)
+ self.assertEqual(response.test_server_port, '80')
+
+ def test_secure(self):
+ "GET a URL through https"
+ response = self.client.get('/test_client/secure_view/', secure=True)
+ self.assertTrue(response.test_was_secure_request)
+ self.assertEqual(response.test_server_port, '443')
+
def test_redirect(self):
"GET a URL that redirects elsewhere"
response = self.client.get('/test_client/redirect_view/')
View
1  tests/test_client/views.py
@@ -68,6 +68,7 @@ def view_with_secure(request):
"A view that indicates if the request was secure"
response = HttpResponse()
response.test_was_secure_request = request.is_secure()
+ response.test_server_port = request.META.get('SERVER_PORT', 80)
return response
def double_redirect_view(request):
Please sign in to comment.
Something went wrong with that request. Please try again.