@@ -397,23 +397,49 @@ def _insert_footer(self, response: web.StreamResponse) -> web.StreamResponse:
397
397
resp .last_modified = filepath .stat ().st_mtime # type: ignore[assignment]
398
398
return resp
399
399
400
+ def _insert_footer_if_exists (
401
+ self , filename : str , response : web .StreamResponse
402
+ ) -> web .StreamResponse :
403
+ """Insert the footer if the file exists, otherwise return a 404 response."""
404
+ resolved_path = self ._directory .joinpath (filename ).resolve ()
405
+ if not resolved_path .is_file ():
406
+ return self ._make_not_found_response (resolved_path )
407
+ return self ._insert_footer (response )
408
+
409
+ def _make_not_found_response (self , raw_path : Path ) -> web .StreamResponse :
410
+ """Create a 404 response with a list of available files under the requested path."""
411
+ while not raw_path .is_dir ():
412
+ raw_path = raw_path .parent
413
+ paths = "\n " .join (
414
+ " {}{}" .format (p .relative_to (self ._directory ), "/" if p .is_dir () else "" )
415
+ for p in raw_path .iterdir ()
416
+ )
417
+ msg = "404: Not Found\n \n Available files under '{}/':\n {}\n " .format (
418
+ raw_path .relative_to (self ._directory ), paths
419
+ )
420
+ return web .Response (text = msg , status = 404 , content_type = "text/plain" )
421
+
400
422
async def _handle (self , request : web .Request ) -> web .StreamResponse :
401
- raw_path = self .modify_request (request )
423
+ loop = asyncio .get_running_loop ()
424
+ raw_path = await loop .run_in_executor (None , self .modify_request , request )
402
425
try :
403
426
response = await super ()._handle (request )
404
427
except HTTPNotFound :
405
- while not raw_path .is_dir ():
406
- raw_path = raw_path .parent
407
- paths = "\n " .join (
408
- " {}{}" .format (p .relative_to (self ._directory ), "/" if p .is_dir () else "" )
409
- for p in raw_path .iterdir ())
410
- msg = "404: Not Found\n \n Available files under '{}/':\n {}\n " .format (
411
- raw_path .relative_to (self ._directory ), paths )
412
- response = web .Response (text = msg , status = 404 , content_type = "text/plain" )
428
+ response = await loop .run_in_executor (
429
+ None , self ._make_not_found_response , raw_path
430
+ )
413
431
else :
414
- response = self ._insert_footer (response )
432
+ # With aiohttp 3.10+, we need to also check if the file actually
433
+ # exists since the base class does not check this anymore as its
434
+ # done in the response to enable handling various compressed files.
435
+ response = await loop .run_in_executor (
436
+ None ,
437
+ self ._insert_footer_if_exists ,
438
+ request .match_info ["filename" ],
439
+ response ,
440
+ )
415
441
# Inject CORS headers to allow webfonts to load correctly
416
- response .headers [' Access-Control-Allow-Origin' ] = '*'
442
+ response .headers [" Access-Control-Allow-Origin" ] = "*"
417
443
418
444
if not self ._browser_cache :
419
445
# Add no-cache header to avoid browser caching in local development.
0 commit comments