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

View File

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

View File

@ -6,9 +6,11 @@ import pickle
from django.core.exceptions import SuspiciousOperation from django.core.exceptions import SuspiciousOperation
from django.http import (QueryDict, HttpResponse, HttpResponseRedirect, from django.http import (QueryDict, HttpResponse, HttpResponseRedirect,
HttpResponsePermanentRedirect, HttpResponseNotModified, HttpResponsePermanentRedirect, HttpResponseNotAllowed,
HttpResponseNotModified,
SimpleCookie, BadHeaderError, SimpleCookie, BadHeaderError,
parse_cookie) parse_cookie)
from django.test import TestCase
from django.utils import six from django.utils import six
from django.utils import unittest from django.utils import unittest
@ -330,7 +332,16 @@ class HttpResponseTests(unittest.TestCase):
HttpResponsePermanentRedirect, url) 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): def test_not_modified(self):
response = HttpResponseNotModified() response = HttpResponseNotModified()
self.assertEqual(response.status_code, 304) self.assertEqual(response.status_code, 304)
@ -339,6 +350,14 @@ class HttpResponseSubclassesTests(unittest.TestCase):
response.content = "Hello dear" response.content = "Hello dear"
self.assertNotIn('content-type', response) 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): class CookieTests(unittest.TestCase):
def test_encode(self): def test_encode(self):