Commit 44c09de5 authored by Claude Paroz's avatar Claude Paroz
Browse files

Fixed #18678 -- HttpResponse init arguments allowed for subclasses

Thanks hp1337@gmail.com for the report.
parent 03671ad7
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -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):
+8 −6
Original line number Diff line number Diff line
@@ -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

+21 −2
Original line number Diff line number Diff line
@@ -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):