Fixed #26452 -- Loaded middleware on server start rather than on first request.

This commit is contained in:
David Evans 2016-04-03 14:43:51 +01:00 committed by Tim Graham
parent 23aa700b78
commit 99bb7fcc18
4 changed files with 15 additions and 24 deletions

View File

@ -6,7 +6,6 @@ import logging
import re import re
import sys import sys
from io import BytesIO from io import BytesIO
from threading import Lock
from django import http from django import http
from django.conf import settings from django.conf import settings
@ -147,18 +146,13 @@ class WSGIRequest(http.HttpRequest):
class WSGIHandler(base.BaseHandler): class WSGIHandler(base.BaseHandler):
initLock = Lock()
request_class = WSGIRequest request_class = WSGIRequest
def __call__(self, environ, start_response): def __init__(self, *args, **kwargs):
# Set up middleware if needed. We couldn't do this earlier, because super(WSGIHandler, self).__init__(*args, **kwargs)
# settings weren't available. self.load_middleware()
if self._request_middleware is None:
with self.initLock:
# Check that middleware is still uninitialized.
if self._request_middleware is None:
self.load_middleware()
def __call__(self, environ, start_response):
set_script_prefix(get_script_name(environ)) set_script_prefix(get_script_name(environ))
signals.request_started.send(sender=self.__class__, environ=environ) signals.request_started.send(sender=self.__class__, environ=environ)
try: try:

View File

@ -714,6 +714,9 @@ Miscellaneous
:class:`~django.contrib.postgres.fields.RangeField`, you should change the :class:`~django.contrib.postgres.fields.RangeField`, you should change the
``base_field`` attribute. ``base_field`` attribute.
* Middleware classes are now initialized when the server starts rather than
during the first request.
.. _deprecated-features-1.10: .. _deprecated-features-1.10:
Features deprecated in 1.10 Features deprecated in 1.10

View File

@ -260,8 +260,12 @@ of caveats:
define ``__init__`` as requiring any arguments. define ``__init__`` as requiring any arguments.
* Unlike the ``process_*`` methods which get called once per request, * Unlike the ``process_*`` methods which get called once per request,
``__init__`` gets called only *once*, when the Web server responds to the ``__init__`` gets called only *once*, when the Web server starts.
first request.
.. versionchanged:: 1.10
In older versions, ``__init__`` was not called until the Web server
responded to its first request.
Marking middleware as unused Marking middleware as unused
~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -20,19 +20,9 @@ class HandlerTests(SimpleTestCase):
def tearDown(self): def tearDown(self):
request_started.connect(close_old_connections) request_started.connect(close_old_connections)
# Mangle settings so the handler will fail def test_middleware_initialized(self):
@override_settings(MIDDLEWARE_CLASSES=42)
def test_lock_safety(self):
"""
Tests for bug #11193 (errors inside middleware shouldn't leave
the initLock locked).
"""
# Try running the handler, it will fail in load_middleware
handler = WSGIHandler() handler = WSGIHandler()
self.assertEqual(handler.initLock.locked(), False) self.assertIsNotNone(handler._request_middleware)
with self.assertRaises(Exception):
handler(None, None)
self.assertEqual(handler.initLock.locked(), False)
def test_bad_path_info(self): def test_bad_path_info(self):
"""Tests for bug #15672 ('request' referenced before assignment)""" """Tests for bug #15672 ('request' referenced before assignment)"""