Fixed #18678 -- HttpResponse init arguments allowed for subclasses

Thanks hp1337@gmail.com for the report.
This commit is contained in:
Claude Paroz 2012-08-23 10:56:55 +02:00
parent 03671ad7e3
commit 44c09de555
3 changed files with 33 additions and 12 deletions

View File

@ -728,11 +728,11 @@ class HttpResponse(object):
class HttpResponseRedirectBase(HttpResponse):
allowed_schemes = ['http', 'https', 'ftp']
def __init__(self, redirect_to):
def __init__(self, redirect_to, *args, **kwargs):
parsed = urlparse(redirect_to)
if parsed.scheme and parsed.scheme not in self.allowed_schemes:
raise SuspiciousOperation("Unsafe redirect to URL with protocol '%s'" % parsed.scheme)
super(HttpResponseRedirectBase, self).__init__()
super(HttpResponseRedirectBase, self).__init__(*args, **kwargs)
self['Location'] = iri_to_uri(redirect_to)
class HttpResponseRedirect(HttpResponseRedirectBase):
@ -766,8 +766,8 @@ class HttpResponseForbidden(HttpResponse):
class HttpResponseNotAllowed(HttpResponse):
status_code = 405
def __init__(self, permitted_methods):
super(HttpResponseNotAllowed, self).__init__()
def __init__(self, permitted_methods, *args, **kwargs):
super(HttpResponseNotAllowed, self).__init__(*args, **kwargs)
self['Allow'] = ', '.join(permitted_methods)
class HttpResponseGone(HttpResponse):

View File

@ -731,10 +731,11 @@ types of HTTP responses. Like ``HttpResponse``, these subclasses live in
.. class:: HttpResponseRedirect
The constructor takes a single argument -- the path to redirect to. This
can be a fully qualified URL (e.g. ``'http://www.yahoo.com/search/'``) or
an absolute path with no domain (e.g. ``'/search/'``). Note that this
returns an HTTP status code 302.
The first argument to the constructor is required -- the path to redirect
to. This can be a fully qualified URL
(e.g. ``'http://www.yahoo.com/search/'``) or an absolute path with no
domain (e.g. ``'/search/'``). See :class:`HttpResponse` for other optional
constructor arguments. Note that this returns an HTTP status code 302.
.. class:: HttpResponsePermanentRedirect
@ -761,8 +762,9 @@ types of HTTP responses. Like ``HttpResponse``, these subclasses live in
.. class:: HttpResponseNotAllowed
Like :class:`HttpResponse`, but uses a 405 status code. Takes a single,
required argument: a list of permitted methods (e.g. ``['GET', 'POST']``).
Like :class:`HttpResponse`, but uses a 405 status code. The first argument
to the constructor is required: a list of permitted methods (e.g.
``['GET', 'POST']``).
.. class:: HttpResponseGone

View File

@ -6,9 +6,11 @@ import pickle
from django.core.exceptions import SuspiciousOperation
from django.http import (QueryDict, HttpResponse, HttpResponseRedirect,
HttpResponsePermanentRedirect, HttpResponseNotModified,
HttpResponsePermanentRedirect, HttpResponseNotAllowed,
HttpResponseNotModified,
SimpleCookie, BadHeaderError,
parse_cookie)
from django.test import TestCase
from django.utils import six
from django.utils import unittest
@ -330,7 +332,16 @@ class HttpResponseTests(unittest.TestCase):
HttpResponsePermanentRedirect, url)
class HttpResponseSubclassesTests(unittest.TestCase):
class HttpResponseSubclassesTests(TestCase):
def test_redirect(self):
response = HttpResponseRedirect('/redirected/')
self.assertEqual(response.status_code, 302)
# Test that standard HttpResponse init args can be used
response = HttpResponseRedirect('/redirected/',
content='The resource has temporarily moved',
content_type='text/html')
self.assertContains(response, 'The resource has temporarily moved', status_code=302)
def test_not_modified(self):
response = HttpResponseNotModified()
self.assertEqual(response.status_code, 304)
@ -339,6 +350,14 @@ class HttpResponseSubclassesTests(unittest.TestCase):
response.content = "Hello dear"
self.assertNotIn('content-type', response)
def test_not_allowed(self):
response = HttpResponseNotAllowed(['GET'])
self.assertEqual(response.status_code, 405)
# Test that standard HttpResponse init args can be used
response = HttpResponseNotAllowed(['GET'],
content='Only the GET method is allowed',
content_type='text/html')
self.assertContains(response, 'Only the GET method is allowed', status_code=405)
class CookieTests(unittest.TestCase):
def test_encode(self):