Django 1.11: MIDDLEWARE_CLASSES setting is deprecated.

Django provides MiddlewareMixin to upgrade old-style middlewares. See
https://docs.djangoproject.com/en/1.11/topics/http/middleware/#upgrading-middleware
This commit is contained in:
Umair Khan 2017-05-18 14:56:03 +05:00 committed by Tim Abbott
parent 1e9c87855c
commit 95fc16d90d
3 changed files with 61 additions and 9 deletions

View File

@ -6,6 +6,7 @@ from typing import Any, AnyStr, Callable, Dict, Iterable, List, MutableMapping,
from django.conf import settings
from django.core.exceptions import DisallowedHost
from django.utils.translation import ugettext as _
from django.utils.deprecation import MiddlewareMixin
from zerver.lib.response import json_error
from zerver.lib.request import JsonableError
@ -228,7 +229,7 @@ def write_log_line(log_data, path, method, remote_ip, email, client_name,
error_data = u"[content more than 100 characters]"
logger.info('status=%3d, data=%s, uid=%s' % (status_code, error_data, email))
class LogRequests(object):
class LogRequests(MiddlewareMixin):
# We primarily are doing logging using the process_view hook, but
# for some views, process_view isn't run, so we call the start
# method here too
@ -281,7 +282,7 @@ class LogRequests(object):
error_content=content, error_content_iter=content_iter)
return response
class JsonErrorHandler(object):
class JsonErrorHandler(MiddlewareMixin):
def process_exception(self, request, exception):
# type: (HttpRequest, Any) -> Optional[HttpResponse]
if hasattr(exception, 'to_json_error_msg') and callable(exception.to_json_error_msg):
@ -296,7 +297,7 @@ class JsonErrorHandler(object):
return json_error(_("Internal server error"), status=500)
return None
class TagRequests(object):
class TagRequests(MiddlewareMixin):
def process_view(self, request, view_func, args, kwargs):
# type: (HttpRequest, Callable[..., HttpResponse], List[str], Dict[str, Any]) -> None
self.process_request(request)
@ -315,7 +316,7 @@ def csrf_failure(request, reason=""):
else:
return html_csrf_failure(request, reason)
class RateLimitMiddleware(object):
class RateLimitMiddleware(MiddlewareMixin):
def process_response(self, request, response):
# type: (HttpRequest, HttpResponse) -> HttpResponse
if not settings.RATE_LIMITING:
@ -342,7 +343,7 @@ class RateLimitMiddleware(object):
resp['Retry-After'] = request._ratelimit_secs_to_freedom
return resp
class FlushDisplayRecipientCache(object):
class FlushDisplayRecipientCache(MiddlewareMixin):
def process_response(self, request, response):
# type: (HttpRequest, HttpResponse) -> HttpResponse
# We flush the per-request caches after every request, so they
@ -416,7 +417,7 @@ class SessionHostDomainMiddleware(SessionMiddleware):
httponly=settings.SESSION_COOKIE_HTTPONLY or None)
return response
class SetRemoteAddrFromForwardedFor(object):
class SetRemoteAddrFromForwardedFor(MiddlewareMixin):
"""
Middleware that sets REMOTE_ADDR based on the HTTP_X_FORWARDED_FOR.

View File

@ -4,14 +4,18 @@ from __future__ import print_function
import sys
import tornado.web
import logging
import six
from django import http
from django.conf import settings
from django.core.handlers.wsgi import WSGIRequest, get_script_name
from django.core.handlers import base
from django.core.handlers.exception import convert_exception_to_response
from django.core.urlresolvers import set_script_prefix
from django.core import signals
from django.core import exceptions, urlresolvers
from django.core.exceptions import MiddlewareNotUsed
from django.http import HttpRequest, HttpResponse
from django.utils.module_loading import import_string
from threading import Lock
from tornado.wsgi import WSGIContainer
from six.moves import urllib
@ -21,7 +25,7 @@ from zerver.lib.response import json_response
from zerver.middleware import async_request_stop, async_request_restart
from zerver.tornado.descriptors import get_descriptor_by_handler_id
from typing import Any, Callable, Dict, List
from typing import Any, Callable, Dict, List, Optional
current_handler_id = 0
handlers = {} # type: Dict[int, AsyncDjangoHandler]
@ -85,7 +89,7 @@ class AsyncDjangoHandler(tornado.web.RequestHandler, base.BaseHandler):
# Set up middleware if needed. We couldn't do this earlier, because
# settings weren't available.
self._request_middleware = None # type: ignore # See self._request_middleware block below
self._request_middleware = None # type: Optional[List[Callable]]
self.initLock.acquire()
# Check that middleware is still uninitialised.
if self._request_middleware is None:
@ -101,6 +105,53 @@ class AsyncDjangoHandler(tornado.web.RequestHandler, base.BaseHandler):
descriptor = get_descriptor_by_handler_id(self.handler_id)
return "AsyncDjangoHandler<%s, %s>" % (self.handler_id, descriptor)
def load_middleware(self):
# type: () -> None
"""
Populate middleware lists from settings.MIDDLEWARE. This is copied
from Django. This uses settings.MIDDLEWARE setting with the old
business logic. The middleware architecture is not compatible
with our asynchronous handlers. The problem occurs when we return
None from our handler. The Django middlewares throw exception
because they can't handler None, so we can either upgrade the Django
middlewares or just override this method to use the new setting with
the old logic. The added advantage is that due to this our event
system code doesn't change.
"""
self._request_middleware = [] # type: Optional[List[Callable]]
self._view_middleware = [] # type: List[Callable]
self._template_response_middleware = [] # type: List[Callable]
self._response_middleware = [] # type: List[Callable]
self._exception_middleware = [] # type: List[Callable]
handler = convert_exception_to_response(self._legacy_get_response)
for middleware_path in settings.MIDDLEWARE:
mw_class = import_string(middleware_path)
try:
mw_instance = mw_class()
except MiddlewareNotUsed as exc:
if settings.DEBUG:
if six.text_type(exc):
base.logger.debug('MiddlewareNotUsed(%r): %s', middleware_path, exc)
else:
base.logger.debug('MiddlewareNotUsed: %r', middleware_path)
continue
if hasattr(mw_instance, 'process_request'):
self._request_middleware.append(mw_instance.process_request)
if hasattr(mw_instance, 'process_view'):
self._view_middleware.append(mw_instance.process_view)
if hasattr(mw_instance, 'process_template_response'):
self._template_response_middleware.insert(0, mw_instance.process_template_response)
if hasattr(mw_instance, 'process_response'):
self._response_middleware.insert(0, mw_instance.process_response)
if hasattr(mw_instance, 'process_exception'):
self._exception_middleware.insert(0, mw_instance.process_exception)
# We only assign to this when initialization is complete as it is used
# as a flag for initialization being complete.
self._middleware_chain = handler
def get(self, *args, **kwargs):
# type: (*Any, **Any) -> None
environ = WSGIContainer.environ(self.request)

View File

@ -344,7 +344,7 @@ TEMPLATES = [
non_html_template_engine_settings,
]
MIDDLEWARE_CLASSES = (
MIDDLEWARE = (
# With the exception of it's dependencies,
# our logging middleware should be the top middleware item.
'zerver.middleware.TagRequests',