@@ -334,15 +334,15 @@ def __init__(self, *args: Any, add_tail_snippet: bool = False,
334
334
super ().__init__ (* args , ** kwargs )
335
335
self ._show_index = True
336
336
337
- def modify_request (self , request : web .Request ) -> None :
337
+ def modify_request (self , request : web .Request ) -> Path :
338
338
"""
339
339
Apply common path conventions eg. / > /index.html, /foobar > /foobar.html
340
340
"""
341
341
filename = URL .build (path = request .match_info ['filename' ], encoded = True ).path
342
- raw_path = self ._directory . joinpath ( filename )
342
+ raw_path = self ._directory / filename
343
343
try :
344
344
filepath = raw_path .resolve (strict = True )
345
- except FileNotFoundError :
345
+ except ( FileNotFoundError , NotADirectoryError ) :
346
346
try :
347
347
html_file = raw_path .with_name (raw_path .name + '.html' ).resolve ().relative_to (self ._directory )
348
348
except (FileNotFoundError , ValueError ):
@@ -358,6 +358,7 @@ def modify_request(self, request: web.Request) -> None:
358
358
except ValueError :
359
359
# path is not not relative to self._directory
360
360
pass
361
+ return raw_path
361
362
362
363
def _insert_footer (self , response : web .StreamResponse ) -> web .StreamResponse :
363
364
if not isinstance (response , web .FileResponse ) or not self ._add_tail_snippet :
@@ -377,17 +378,20 @@ def _insert_footer(self, response: web.StreamResponse) -> web.StreamResponse:
377
378
return resp
378
379
379
380
async def _handle (self , request : web .Request ) -> web .StreamResponse :
380
- self .modify_request (request )
381
+ raw_path = self .modify_request (request )
381
382
try :
382
383
response = await super ()._handle (request )
383
- response = self ._insert_footer (response )
384
- except HTTPNotModified :
385
- raise
386
384
except HTTPNotFound :
387
- # TODO include list of files in 404 body
388
- _404_msg = '404: Not Found\n '
389
- response = web .Response (body = _404_msg .encode (), status = 404 , content_type = 'text/plain' )
385
+ while not raw_path .is_dir ():
386
+ raw_path = raw_path .parent
387
+ paths = "\n " .join (
388
+ " {}{}" .format (p .relative_to (self ._directory ), "/" if p .is_dir () else "" )
389
+ for p in raw_path .iterdir ())
390
+ msg = "404: Not Found\n \n Available files under '{}/':\n {}\n " .format (
391
+ raw_path .relative_to (self ._directory ), paths )
392
+ response = web .Response (text = msg , status = 404 , content_type = "text/plain" )
390
393
else :
394
+ response = self ._insert_footer (response )
391
395
# Inject CORS headers to allow webfonts to load correctly
392
396
response .headers ['Access-Control-Allow-Origin' ] = '*'
393
397
0 commit comments