Skip to content

Commit 92f4884

Browse files
committed
Fix middleware auto selection
1 parent 906beed commit 92f4884

File tree

1 file changed

+20
-4
lines changed

1 file changed

+20
-4
lines changed

src/servestatic/middleware.py

+20-4
Original file line numberDiff line numberDiff line change
@@ -162,24 +162,30 @@ def __call__(self, request):
162162
if iscoroutinefunction(self.get_response):
163163
return self.acall(request)
164164

165-
# Force Django >= 3.2 to use async file responses
165+
# Force Django >= 3.2 use async file responses when using ASGI, even
166+
# if Django forces this middleware to run synchronously
166167
if django.VERSION >= (3, 2):
167168
return asyncio.run(self.acall(request))
168169

169170
# Django version has no async uspport
170171
return self.call(request)
171172

172173
def call(self, request):
173-
"""TODO: This can be deleted once Django 4.2 is the minimum supported version."""
174+
"""If the URL contains a static file, serve it.
175+
Otherwise, continue to the next middleware."""
174176
if self.autorefresh:
175177
static_file = self.find_file(request.path_info)
176178
else:
177179
static_file = self.files.get(request.path_info)
178180
if static_file is not None:
179181
return self.serve(static_file, request)
182+
183+
# Run the next middleware in the stack
180184
return self.get_response(request)
181185

182186
async def acall(self, request):
187+
"""If the URL contains a static file, serve it.
188+
Otherwise, continue to the next middleware."""
183189
if self.autorefresh and hasattr(asyncio, "to_thread"):
184190
# Use a thread while searching disk for files on Python 3.9+
185191
static_file = await asyncio.to_thread(self.find_file, request.path_info)
@@ -189,7 +195,13 @@ async def acall(self, request):
189195
static_file = self.files.get(request.path_info)
190196
if static_file is not None:
191197
return await self.aserve(static_file, request)
192-
return await self.get_response(request)
198+
199+
# Run the next middleware in the stack. Note that get_response can sometimes be sync if
200+
# middleware was run in mixed sync-async mode
201+
# https://docs.djangoproject.com/en/stable/topics/http/middleware/#asynchronous-support
202+
if iscoroutinefunction(self.get_response):
203+
return await self.get_response(request)
204+
return self.get_response(request)
193205

194206
@staticmethod
195207
def serve(static_file, request):
@@ -320,7 +332,11 @@ class AsyncToSyncIterator:
320332
This converter must create a temporary event loop in a thread for two reasons:
321333
1) Allows us to stream the iterator instead of buffering all contents in memory.
322334
2) Allows the iterator to be used in environments where an event loop may not exist,
323-
or may be closed unexpectedly."""
335+
or may be closed unexpectedly.
336+
337+
Currently used to add async file compatibility to Django WSGI and Django versions
338+
that do not support __aiter__.
339+
"""
324340

325341
def __init__(self, iterator: AsyncIterable):
326342
self.iterator = iterator

0 commit comments

Comments
 (0)