1. import asyncio
    
  2. import threading
    
  3. 
    
  4. from asgiref.sync import async_to_sync
    
  5. 
    
  6. from django.contrib.admindocs.middleware import XViewMiddleware
    
  7. from django.contrib.auth.middleware import (
    
  8.     AuthenticationMiddleware,
    
  9.     RemoteUserMiddleware,
    
  10. )
    
  11. from django.contrib.flatpages.middleware import FlatpageFallbackMiddleware
    
  12. from django.contrib.messages.middleware import MessageMiddleware
    
  13. from django.contrib.redirects.middleware import RedirectFallbackMiddleware
    
  14. from django.contrib.sessions.middleware import SessionMiddleware
    
  15. from django.contrib.sites.middleware import CurrentSiteMiddleware
    
  16. from django.db import connection
    
  17. from django.http.request import HttpRequest
    
  18. from django.http.response import HttpResponse
    
  19. from django.middleware.cache import (
    
  20.     CacheMiddleware,
    
  21.     FetchFromCacheMiddleware,
    
  22.     UpdateCacheMiddleware,
    
  23. )
    
  24. from django.middleware.clickjacking import XFrameOptionsMiddleware
    
  25. from django.middleware.common import BrokenLinkEmailsMiddleware, CommonMiddleware
    
  26. from django.middleware.csrf import CsrfViewMiddleware
    
  27. from django.middleware.gzip import GZipMiddleware
    
  28. from django.middleware.http import ConditionalGetMiddleware
    
  29. from django.middleware.locale import LocaleMiddleware
    
  30. from django.middleware.security import SecurityMiddleware
    
  31. from django.test import SimpleTestCase
    
  32. from django.utils.deprecation import MiddlewareMixin
    
  33. 
    
  34. 
    
  35. class MiddlewareMixinTests(SimpleTestCase):
    
  36.     middlewares = [
    
  37.         AuthenticationMiddleware,
    
  38.         BrokenLinkEmailsMiddleware,
    
  39.         CacheMiddleware,
    
  40.         CommonMiddleware,
    
  41.         ConditionalGetMiddleware,
    
  42.         CsrfViewMiddleware,
    
  43.         CurrentSiteMiddleware,
    
  44.         FetchFromCacheMiddleware,
    
  45.         FlatpageFallbackMiddleware,
    
  46.         GZipMiddleware,
    
  47.         LocaleMiddleware,
    
  48.         MessageMiddleware,
    
  49.         RedirectFallbackMiddleware,
    
  50.         RemoteUserMiddleware,
    
  51.         SecurityMiddleware,
    
  52.         SessionMiddleware,
    
  53.         UpdateCacheMiddleware,
    
  54.         XFrameOptionsMiddleware,
    
  55.         XViewMiddleware,
    
  56.     ]
    
  57. 
    
  58.     def test_repr(self):
    
  59.         class GetResponse:
    
  60.             def __call__(self):
    
  61.                 return HttpResponse()
    
  62. 
    
  63.         def get_response():
    
  64.             return HttpResponse()
    
  65. 
    
  66.         self.assertEqual(
    
  67.             repr(MiddlewareMixin(GetResponse())),
    
  68.             "<MiddlewareMixin get_response=GetResponse>",
    
  69.         )
    
  70.         self.assertEqual(
    
  71.             repr(MiddlewareMixin(get_response)),
    
  72.             "<MiddlewareMixin get_response="
    
  73.             "MiddlewareMixinTests.test_repr.<locals>.get_response>",
    
  74.         )
    
  75.         self.assertEqual(
    
  76.             repr(CsrfViewMiddleware(GetResponse())),
    
  77.             "<CsrfViewMiddleware get_response=GetResponse>",
    
  78.         )
    
  79.         self.assertEqual(
    
  80.             repr(CsrfViewMiddleware(get_response)),
    
  81.             "<CsrfViewMiddleware get_response="
    
  82.             "MiddlewareMixinTests.test_repr.<locals>.get_response>",
    
  83.         )
    
  84. 
    
  85.     def test_passing_explicit_none(self):
    
  86.         msg = "get_response must be provided."
    
  87.         for middleware in self.middlewares:
    
  88.             with self.subTest(middleware=middleware):
    
  89.                 with self.assertRaisesMessage(ValueError, msg):
    
  90.                     middleware(None)
    
  91. 
    
  92.     def test_coroutine(self):
    
  93.         async def async_get_response(request):
    
  94.             return HttpResponse()
    
  95. 
    
  96.         def sync_get_response(request):
    
  97.             return HttpResponse()
    
  98. 
    
  99.         for middleware in self.middlewares:
    
  100.             with self.subTest(middleware=middleware.__qualname__):
    
  101.                 # Middleware appears as coroutine if get_function is
    
  102.                 # a coroutine.
    
  103.                 middleware_instance = middleware(async_get_response)
    
  104.                 self.assertIs(asyncio.iscoroutinefunction(middleware_instance), True)
    
  105.                 # Middleware doesn't appear as coroutine if get_function is not
    
  106.                 # a coroutine.
    
  107.                 middleware_instance = middleware(sync_get_response)
    
  108.                 self.assertIs(asyncio.iscoroutinefunction(middleware_instance), False)
    
  109. 
    
  110.     def test_sync_to_async_uses_base_thread_and_connection(self):
    
  111.         """
    
  112.         The process_request() and process_response() hooks must be called with
    
  113.         the sync_to_async thread_sensitive flag enabled, so that database
    
  114.         operations use the correct thread and connection.
    
  115.         """
    
  116. 
    
  117.         def request_lifecycle():
    
  118.             """Fake request_started/request_finished."""
    
  119.             return (threading.get_ident(), id(connection))
    
  120. 
    
  121.         async def get_response(self):
    
  122.             return HttpResponse()
    
  123. 
    
  124.         class SimpleMiddleWare(MiddlewareMixin):
    
  125.             def process_request(self, request):
    
  126.                 request.thread_and_connection = request_lifecycle()
    
  127. 
    
  128.             def process_response(self, request, response):
    
  129.                 response.thread_and_connection = request_lifecycle()
    
  130.                 return response
    
  131. 
    
  132.         threads_and_connections = []
    
  133.         threads_and_connections.append(request_lifecycle())
    
  134. 
    
  135.         request = HttpRequest()
    
  136.         response = async_to_sync(SimpleMiddleWare(get_response))(request)
    
  137.         threads_and_connections.append(request.thread_and_connection)
    
  138.         threads_and_connections.append(response.thread_and_connection)
    
  139. 
    
  140.         threads_and_connections.append(request_lifecycle())
    
  141. 
    
  142.         self.assertEqual(len(threads_and_connections), 4)
    
  143.         self.assertEqual(len(set(threads_and_connections)), 1)