Kaydet (Commit) bb0b4b70 authored tarafından Tim Graham's avatar Tim Graham

Fixed #26052 -- Moved conditional_content_removal() processing to the test client.

üst bd145e72
...@@ -24,10 +24,6 @@ logger = logging.getLogger('django.request') ...@@ -24,10 +24,6 @@ logger = logging.getLogger('django.request')
class BaseHandler(object): class BaseHandler(object):
# Changes that are always applied to a response (in this order).
response_fixes = [
http.conditional_content_removal,
]
def __init__(self): def __init__(self):
self._request_middleware = None self._request_middleware = None
...@@ -230,7 +226,6 @@ class BaseHandler(object): ...@@ -230,7 +226,6 @@ class BaseHandler(object):
"%s.process_response didn't return an " "%s.process_response didn't return an "
"HttpResponse object. It returned None instead." "HttpResponse object. It returned None instead."
% (middleware_method.__self__.__class__.__name__)) % (middleware_method.__self__.__class__.__name__))
response = self.apply_response_fixes(request, response)
except Exception: # Any exception should be gathered and handled except Exception: # Any exception should be gathered and handled
signals.got_request_exception.send(sender=self.__class__, request=request) signals.got_request_exception.send(sender=self.__class__, request=request)
response = self.handle_uncaught_exception(request, resolver, sys.exc_info()) response = self.handle_uncaught_exception(request, resolver, sys.exc_info())
...@@ -289,13 +284,3 @@ class BaseHandler(object): ...@@ -289,13 +284,3 @@ class BaseHandler(object):
# Return an HttpResponse that displays a friendly error message. # Return an HttpResponse that displays a friendly error message.
callback, param_dict = resolver.resolve_error_handler(500) callback, param_dict = resolver.resolve_error_handler(500)
return callback(request, **param_dict) return callback(request, **param_dict)
def apply_response_fixes(self, request, response):
"""
Applies each of the functions in self.response_fixes to the request and
response, modifying the response in the process. Returns the new
response.
"""
for func in self.response_fixes:
response = func(request, response)
return response
...@@ -9,7 +9,6 @@ from django.http.response import ( ...@@ -9,7 +9,6 @@ from django.http.response import (
HttpResponsePermanentRedirect, HttpResponseRedirect, HttpResponsePermanentRedirect, HttpResponseRedirect,
HttpResponseServerError, JsonResponse, StreamingHttpResponse, HttpResponseServerError, JsonResponse, StreamingHttpResponse,
) )
from django.http.utils import conditional_content_removal
__all__ = [ __all__ = [
'SimpleCookie', 'parse_cookie', 'HttpRequest', 'QueryDict', 'SimpleCookie', 'parse_cookie', 'HttpRequest', 'QueryDict',
...@@ -19,5 +18,4 @@ __all__ = [ ...@@ -19,5 +18,4 @@ __all__ = [
'HttpResponseBadRequest', 'HttpResponseForbidden', 'HttpResponseNotFound', 'HttpResponseBadRequest', 'HttpResponseForbidden', 'HttpResponseNotFound',
'HttpResponseNotAllowed', 'HttpResponseGone', 'HttpResponseServerError', 'HttpResponseNotAllowed', 'HttpResponseGone', 'HttpResponseServerError',
'Http404', 'BadHeaderError', 'JsonResponse', 'FileResponse', 'Http404', 'BadHeaderError', 'JsonResponse', 'FileResponse',
'conditional_content_removal',
] ]
"""
Functions that modify an HTTP request or response in some way.
"""
# This group of functions are run as part of the response handling, after
# everything else, including all response middleware. Think of them as
# "compulsory response middleware". Be careful about what goes here, because
# it's a little fiddly to override this behavior, so they should be truly
# universally applicable.
def conditional_content_removal(request, response):
"""
Removes the content of responses for HEAD requests, 1xx, 204 and 304
responses. Ensures compliance with RFC 2616, section 4.3.
"""
if 100 <= response.status_code < 200 or response.status_code in (204, 304):
if response.streaming:
response.streaming_content = []
else:
response.content = b''
response['Content-Length'] = '0'
if request.method == 'HEAD':
if response.streaming:
response.streaming_content = []
else:
response.content = b''
return response
...@@ -92,6 +92,26 @@ def closing_iterator_wrapper(iterable, close): ...@@ -92,6 +92,26 @@ def closing_iterator_wrapper(iterable, close):
request_finished.connect(close_old_connections) request_finished.connect(close_old_connections)
def conditional_content_removal(request, response):
"""
Simulate the behavior of most Web servers by removing the content of
responses for HEAD requests, 1xx, 204, and 304 responses. Ensures
compliance with RFC 2616, section 4.3.
"""
if 100 <= response.status_code < 200 or response.status_code in (204, 304):
if response.streaming:
response.streaming_content = []
else:
response.content = b''
response['Content-Length'] = '0'
if request.method == 'HEAD':
if response.streaming:
response.streaming_content = []
else:
response.content = b''
return response
class ClientHandler(BaseHandler): class ClientHandler(BaseHandler):
""" """
A HTTP Handler that can be used for testing purposes. Uses the WSGI A HTTP Handler that can be used for testing purposes. Uses the WSGI
...@@ -120,6 +140,10 @@ class ClientHandler(BaseHandler): ...@@ -120,6 +140,10 @@ class ClientHandler(BaseHandler):
# Request goes through middleware. # Request goes through middleware.
response = self.get_response(request) response = self.get_response(request)
# Simulate behaviors of most Web servers.
conditional_content_removal(request, response)
# Attach the originating request to the response so that it could be # Attach the originating request to the response so that it could be
# later retrieved. # later retrieved.
response.wsgi_request = request response.wsgi_request = request
......
...@@ -778,6 +778,11 @@ Miscellaneous ...@@ -778,6 +778,11 @@ Miscellaneous
attribute to ``False`` to disable it. You could also add the ``novalidate`` attribute to ``False`` to disable it. You could also add the ``novalidate``
attribute to ``<form>`` if you don't want browser validation. attribute to ``<form>`` if you don't want browser validation.
* The WSGI handler no longer removes content of responses from ``HEAD``
requests or responses with a ``status_code`` of 100-199, 204, or 304. Most
Web servers already implement this behavior. Responses retrieved using the
Django test client continue to have these "response fixes" applied.
.. _deprecated-features-1.10: .. _deprecated-features-1.10:
Features deprecated in 1.10 Features deprecated in 1.10
......
...@@ -4,8 +4,8 @@ import gzip ...@@ -4,8 +4,8 @@ import gzip
import io import io
from django.http import HttpRequest, HttpResponse, StreamingHttpResponse from django.http import HttpRequest, HttpResponse, StreamingHttpResponse
from django.http.utils import conditional_content_removal
from django.test import SimpleTestCase from django.test import SimpleTestCase
from django.test.client import conditional_content_removal
# based on Python 3.3's gzip.compress # based on Python 3.3's gzip.compress
...@@ -19,12 +19,12 @@ def gzip_compress(data): ...@@ -19,12 +19,12 @@ def gzip_compress(data):
return buf.getvalue() return buf.getvalue()
class HttpUtilTests(SimpleTestCase): class ConditionalContentTests(SimpleTestCase):
def test_conditional_content_removal(self): def test_conditional_content_removal(self):
""" """
Tests that content is removed from regular and streaming responses with Content is removed from regular and streaming responses with a
a status_code of 100-199, 204, 304 or a method of "HEAD". status_code of 100-199, 204, 304, or a method of "HEAD".
""" """
req = HttpRequest() req = HttpRequest()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment