-
Notifications
You must be signed in to change notification settings - Fork 151
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Running whitenoise behind a WSGI-to-ASGI adapter #251
Comments
Hi @aaronn, it's been one of my long term goals get whitenoise working natively wth asgi, but I just haven't had time to make any progress on this. It should certainly be easier now that I've dropped support for older Python versions and there's no issue with using the |
Does Whitenoise work with Django's Daphne server? I see various reference to using Whitenoise but am confused because Daphne is ASGI yet seems to recommend Whitenoise. However, Whitenoise indicates it doesn't work with ASGI. It would be nice to move to Daphne instead of Gunicorn to make use of websockets but compatibility is contradictory. |
It's possible I was mistaken, but I used to use Whitenoise in Django under ASGI since it interacted with the Django request interface, which we provide a synchronous emulation of. Not sure if it still works, but unless it somehow pierces though Django to get a WSGI handle, it should behave fine behind the synchronous emulation layer. Of course, that requires Django; you can't use it directly with ASGI since it's a different interface. There's |
@andrewgodwin Makes sense! @evansd Is it correct that Whitenoise is compatible with Django served by ASGI if using middleware integration? Just barebones ASGI integration is unsupported? |
Hi, yes DjangoWhitenoise acts as standard Django middleware so should run fine via the compatibility layer. I'd love to get native ASGI integration into Whitenoise but super busy with the medical day job at the moment and ENOTIME :) |
Hi, The consequence is that WhiteNoiseMiddleware does not get the full async It would not be a full async support but maybe implementing It would reduce the time spent in the sync emulation layer (which is a separate Copying the behaviour of MiddlewareMixin, it could roughly look like this: class AsyncWhitenoiseMiddleware(WhiteNoiseMiddleware):
sync_capable = True
async_capable = True
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._async_check()
def _async_check(self):
if asyncio.iscoroutinefunction(self.get_response):
self._is_coroutine = asyncio.coroutines._is_coroutine
def __call__(self, request):
if asyncio.iscoroutinefunction(self.get_response):
return self.__acall__(request)
else:
return super().__call__(request)
async def __acall__(self, request):
response = self.process_request(request)
if response is None:
response = await self.get_response(request)
return response It's probably better to inherit from MiddlewareMixin instead of duplicating code. In the previous code, |
To add to this, what I have in my projects is the following: @sync_and_async_middleware
def whitenoise_middleware(
get_response: Callable[[HttpRequest], HttpResponse | Coroutine[Any, Any, HttpResponse]],
):
mid = WhiteNoiseMiddleware(get_response)
def get_static_file(request: HttpRequest):
# This is copied from WhiteNoiseMiddleware.__call__
if mid.autorefresh:
static_file = mid.find_file(request.path_info)
else:
static_file = mid.files.get(request.path_info)
return mid.serve(static_file, request) if static_file is not None else None
if inspect.iscoroutinefunction(get_response):
aget_static_file = sync_to_async(get_static_file, thread_sensitive=False)
async def middleware(request): # type: ignore
response = await aget_static_file(request)
if response is not None:
return response
return await cast(Awaitable, get_response(request))
else:
def middleware(request):
response = get_static_file(request)
if response is not None:
return response
return get_response(request)
return middleware It is using the new function middleware approach. whitenoise can probably provide something similar and deprecate the use of |
For future onlookers, ASGI support for |
I'm about to deploy a django app. I was originally going to use
uvicorn
with Django 3.0, but after seeingwhitenoise
doesn't work with asgi servers yet was thinking of just reverting back to wsgi.I just came across @tomchristie's pull request and he mentions he's able to (non-ideally) get it working with a wsgi-to-asgi adapter. I was wondering if there's any additional information on how to get that working.
Ideally I'd like to just swap that out whenever whitenoise goes asgi, instead of reverting from
uvicorn
togunicorn
.Thanks for the continued work on a great project!
The text was updated successfully, but these errors were encountered: