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.
This commit is contained in:
parent
19256f300e
commit
99b681e227
|
@ -269,60 +269,68 @@ class RequestFactory(object):
|
|||
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 @@ class Client(RequestFactory):
|
|||
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
|
||||
|
|
|
@ -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
|
||||
=====================================
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -93,6 +93,18 @@ class ClientTest(TestCase):
|
|||
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/')
|
||||
|
|
|
@ -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):
|
||||
|
|
Loading…
Reference in New Issue