daren_project/venv/Lib/site-packages/channels/staticfiles.py

83 lines
2.7 KiB
Python

from urllib.parse import urlparse
from urllib.request import url2pathname
from django.conf import settings
from django.contrib.staticfiles import utils
from django.contrib.staticfiles.views import serve
from django.http import Http404
from .http import AsgiHandler
class StaticFilesWrapper:
"""
ASGI application which wraps another and intercepts requests for static
files, passing them off to Django's static file serving.
"""
def __init__(self, application, staticfiles_handler=None):
self.application = application
self.staticfiles_handler_class = staticfiles_handler or StaticFilesHandler
self.base_url = urlparse(self.get_base_url())
def get_base_url(self):
utils.check_settings()
return settings.STATIC_URL
def _should_handle(self, path):
"""
Checks if the path should be handled. Ignores the path if:
* the host is provided as part of the base_url
* the request's path isn't under the static files path (or equal)
"""
return path.startswith(self.base_url[2]) and not self.base_url[1]
async def __call__(self, scope, receive, send):
# Only even look at HTTP requests
if scope["type"] == "http" and self._should_handle(scope["path"]):
# Serve static content
return await self.staticfiles_handler_class()(
dict(scope, static_base_url=self.base_url), receive, send
)
# Hand off to the main app
return await self.application(scope, receive, send)
class StaticFilesHandler(AsgiHandler):
"""
Subclass of AsgiHandler that serves directly from its get_response.
"""
# TODO: Review hierarchy here. Do we NEED to inherit BaseHandler, AsgiHandler?
async def __call__(self, scope, receive, send):
self.static_base_url = scope["static_base_url"][2]
return await super().__call__(scope, receive, send)
def file_path(self, url):
"""
Returns the relative path to the media file on disk for the given URL.
"""
relative_url = url[len(self.static_base_url) :]
return url2pathname(relative_url)
def serve(self, request):
"""
Actually serves the request path.
"""
return serve(request, self.file_path(request.path), insecure=True)
def get_response(self, request):
"""
Always tries to serve a static file as you don't even get into this
handler subclass without the wrapper directing you here.
"""
try:
return self.serve(request)
except Http404 as e:
if settings.DEBUG:
from django.views import debug
return debug.technical_404_response(request, e)