Funktionierender Prototyp des Serious Games zur Vermittlung von Wissen zu Software-Engineering-Arbeitsmodellen.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

handlers.py 3.4KB

1 year ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. from urllib.parse import urlparse
  2. from urllib.request import url2pathname
  3. from asgiref.sync import sync_to_async
  4. from django.conf import settings
  5. from django.contrib.staticfiles import utils
  6. from django.contrib.staticfiles.views import serve
  7. from django.core.handlers.asgi import ASGIHandler
  8. from django.core.handlers.exception import response_for_exception
  9. from django.core.handlers.wsgi import WSGIHandler, get_path_info
  10. from django.http import Http404
  11. class StaticFilesHandlerMixin:
  12. """
  13. Common methods used by WSGI and ASGI handlers.
  14. """
  15. # May be used to differentiate between handler types (e.g. in a
  16. # request_finished signal)
  17. handles_files = True
  18. def load_middleware(self):
  19. # Middleware are already loaded for self.application; no need to reload
  20. # them for self.
  21. pass
  22. def get_base_url(self):
  23. utils.check_settings()
  24. return settings.STATIC_URL
  25. def _should_handle(self, path):
  26. """
  27. Check if the path should be handled. Ignore the path if:
  28. * the host is provided as part of the base_url
  29. * the request's path isn't under the media path (or equal)
  30. """
  31. return path.startswith(self.base_url[2]) and not self.base_url[1]
  32. def file_path(self, url):
  33. """
  34. Return the relative path to the media file on disk for the given URL.
  35. """
  36. relative_url = url[len(self.base_url[2]) :]
  37. return url2pathname(relative_url)
  38. def serve(self, request):
  39. """Serve the request path."""
  40. return serve(request, self.file_path(request.path), insecure=True)
  41. def get_response(self, request):
  42. try:
  43. return self.serve(request)
  44. except Http404 as e:
  45. return response_for_exception(request, e)
  46. async def get_response_async(self, request):
  47. try:
  48. return await sync_to_async(self.serve, thread_sensitive=False)(request)
  49. except Http404 as e:
  50. return await sync_to_async(response_for_exception, thread_sensitive=False)(
  51. request, e
  52. )
  53. class StaticFilesHandler(StaticFilesHandlerMixin, WSGIHandler):
  54. """
  55. WSGI middleware that intercepts calls to the static files directory, as
  56. defined by the STATIC_URL setting, and serves those files.
  57. """
  58. def __init__(self, application):
  59. self.application = application
  60. self.base_url = urlparse(self.get_base_url())
  61. super().__init__()
  62. def __call__(self, environ, start_response):
  63. if not self._should_handle(get_path_info(environ)):
  64. return self.application(environ, start_response)
  65. return super().__call__(environ, start_response)
  66. class ASGIStaticFilesHandler(StaticFilesHandlerMixin, ASGIHandler):
  67. """
  68. ASGI application which wraps another and intercepts requests for static
  69. files, passing them off to Django's static file serving.
  70. """
  71. def __init__(self, application):
  72. self.application = application
  73. self.base_url = urlparse(self.get_base_url())
  74. async def __call__(self, scope, receive, send):
  75. # Only even look at HTTP requests
  76. if scope["type"] == "http" and self._should_handle(scope["path"]):
  77. # Serve static content
  78. # (the one thing super() doesn't do is __call__, apparently)
  79. return await super().__call__(scope, receive, send)
  80. # Hand off to the main app
  81. return await self.application(scope, receive, send)