1. import asyncio
    
  2. 
    
  3. from django.http import Http404, HttpResponse
    
  4. from django.template import engines
    
  5. from django.template.response import TemplateResponse
    
  6. from django.utils.decorators import (
    
  7.     async_only_middleware,
    
  8.     sync_and_async_middleware,
    
  9.     sync_only_middleware,
    
  10. )
    
  11. 
    
  12. log = []
    
  13. 
    
  14. 
    
  15. class BaseMiddleware:
    
  16.     def __init__(self, get_response):
    
  17.         self.get_response = get_response
    
  18.         if asyncio.iscoroutinefunction(self.get_response):
    
  19.             # Mark the class as async-capable.
    
  20.             self._is_coroutine = asyncio.coroutines._is_coroutine
    
  21. 
    
  22.     def __call__(self, request):
    
  23.         return self.get_response(request)
    
  24. 
    
  25. 
    
  26. class ProcessExceptionMiddleware(BaseMiddleware):
    
  27.     def process_exception(self, request, exception):
    
  28.         return HttpResponse("Exception caught")
    
  29. 
    
  30. 
    
  31. @async_only_middleware
    
  32. class AsyncProcessExceptionMiddleware(BaseMiddleware):
    
  33.     async def process_exception(self, request, exception):
    
  34.         return HttpResponse("Exception caught")
    
  35. 
    
  36. 
    
  37. class ProcessExceptionLogMiddleware(BaseMiddleware):
    
  38.     def process_exception(self, request, exception):
    
  39.         log.append("process-exception")
    
  40. 
    
  41. 
    
  42. class ProcessExceptionExcMiddleware(BaseMiddleware):
    
  43.     def process_exception(self, request, exception):
    
  44.         raise Exception("from process-exception")
    
  45. 
    
  46. 
    
  47. class ProcessViewMiddleware(BaseMiddleware):
    
  48.     def process_view(self, request, view_func, view_args, view_kwargs):
    
  49.         return HttpResponse("Processed view %s" % view_func.__name__)
    
  50. 
    
  51. 
    
  52. @async_only_middleware
    
  53. class AsyncProcessViewMiddleware(BaseMiddleware):
    
  54.     async def process_view(self, request, view_func, view_args, view_kwargs):
    
  55.         return HttpResponse("Processed view %s" % view_func.__name__)
    
  56. 
    
  57. 
    
  58. class ProcessViewNoneMiddleware(BaseMiddleware):
    
  59.     def process_view(self, request, view_func, view_args, view_kwargs):
    
  60.         log.append("processed view %s" % view_func.__name__)
    
  61.         return None
    
  62. 
    
  63. 
    
  64. class ProcessViewTemplateResponseMiddleware(BaseMiddleware):
    
  65.     def process_view(self, request, view_func, view_args, view_kwargs):
    
  66.         template = engines["django"].from_string(
    
  67.             "Processed view {{ view }}{% for m in mw %}\n{{ m }}{% endfor %}"
    
  68.         )
    
  69.         return TemplateResponse(
    
  70.             request,
    
  71.             template,
    
  72.             {"mw": [self.__class__.__name__], "view": view_func.__name__},
    
  73.         )
    
  74. 
    
  75. 
    
  76. class TemplateResponseMiddleware(BaseMiddleware):
    
  77.     def process_template_response(self, request, response):
    
  78.         response.context_data["mw"].append(self.__class__.__name__)
    
  79.         return response
    
  80. 
    
  81. 
    
  82. @async_only_middleware
    
  83. class AsyncTemplateResponseMiddleware(BaseMiddleware):
    
  84.     async def process_template_response(self, request, response):
    
  85.         response.context_data["mw"].append(self.__class__.__name__)
    
  86.         return response
    
  87. 
    
  88. 
    
  89. class LogMiddleware(BaseMiddleware):
    
  90.     def __call__(self, request):
    
  91.         response = self.get_response(request)
    
  92.         log.append((response.status_code, response.content))
    
  93.         return response
    
  94. 
    
  95. 
    
  96. class NoTemplateResponseMiddleware(BaseMiddleware):
    
  97.     def process_template_response(self, request, response):
    
  98.         return None
    
  99. 
    
  100. 
    
  101. @async_only_middleware
    
  102. class AsyncNoTemplateResponseMiddleware(BaseMiddleware):
    
  103.     async def process_template_response(self, request, response):
    
  104.         return None
    
  105. 
    
  106. 
    
  107. class NotFoundMiddleware(BaseMiddleware):
    
  108.     def __call__(self, request):
    
  109.         raise Http404("not found")
    
  110. 
    
  111. 
    
  112. class PaymentMiddleware(BaseMiddleware):
    
  113.     def __call__(self, request):
    
  114.         response = self.get_response(request)
    
  115.         response.status_code = 402
    
  116.         return response
    
  117. 
    
  118. 
    
  119. @async_only_middleware
    
  120. def async_payment_middleware(get_response):
    
  121.     async def middleware(request):
    
  122.         response = await get_response(request)
    
  123.         response.status_code = 402
    
  124.         return response
    
  125. 
    
  126.     return middleware
    
  127. 
    
  128. 
    
  129. @sync_and_async_middleware
    
  130. class SyncAndAsyncMiddleware(BaseMiddleware):
    
  131.     pass
    
  132. 
    
  133. 
    
  134. @sync_only_middleware
    
  135. class DecoratedPaymentMiddleware(PaymentMiddleware):
    
  136.     pass
    
  137. 
    
  138. 
    
  139. class NotSyncOrAsyncMiddleware(BaseMiddleware):
    
  140.     """Middleware that is deliberately neither sync or async."""
    
  141. 
    
  142.     sync_capable = False
    
  143.     async_capable = False
    
  144. 
    
  145.     def __call__(self, request):
    
  146.         return self.get_response(request)