1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
|
--- contrib/python/aiohttp/aiohttp/web_fileresponse.py (4519f9a6f455df2a2d92670c1d43e4da2fdf57a0)
+++ contrib/python/aiohttp/aiohttp/web_fileresponse.py (af2f4ddbeb99de10bbbd64a8995abf061fe8cc5c)
@@ -3,6 +3,7 @@ import os
import pathlib
import sys
from contextlib import suppress
+from importlib.resources.abc import Traversable
from mimetypes import MimeTypes
from stat import S_ISREG
from types import MappingProxyType
@@ -89,7 +90,7 @@ class FileResponse(StreamResponse):
) -> None:
super().__init__(status=status, reason=reason, headers=headers)
- self._path = pathlib.Path(path)
+ self._path = pathlib.Path(path) if not isinstance(path, Traversable) else path
self._chunk_size = chunk_size
async def _sendfile_fallback(
@@ -319,7 +320,7 @@ class FileResponse(StreamResponse):
# can be ignored since the map was cleared above.
if hdrs.CONTENT_TYPE not in self.headers:
self.content_type = (
- CONTENT_TYPES.guess_type(self._path)[0] or FALLBACK_CONTENT_TYPE
+ CONTENT_TYPES.guess_type(self._path.name)[0] or FALLBACK_CONTENT_TYPE
)
if file_encoding:
--- contrib/python/aiohttp/aiohttp/web_urldispatcher.py (4519f9a6f455df2a2d92670c1d43e4da2fdf57a0)
+++ contrib/python/aiohttp/aiohttp/web_urldispatcher.py (af2f4ddbeb99de10bbbd64a8995abf061fe8cc5c)
@@ -11,6 +11,7 @@ import re
import sys
import warnings
from functools import wraps
+from importlib.resources.abc import Traversable, TraversalError
from pathlib import Path
from types import MappingProxyType
from typing import (
@@ -559,7 +560,8 @@ class StaticResource(PrefixResource):
) -> None:
super().__init__(prefix, name=name)
try:
- directory = Path(directory).expanduser().resolve(strict=True)
+ if not isinstance(directory, Traversable):
+ directory = Path(directory).expanduser().resolve(strict=True)
except FileNotFoundError as error:
raise ValueError(f"'{directory}' does not exist") from error
if not directory.is_dir():
@@ -670,7 +672,10 @@ class StaticResource(PrefixResource):
# where the static dir is totally different
raise HTTPForbidden()
- unresolved_path = self._directory.joinpath(filename)
+ try:
+ unresolved_path = self._directory.joinpath(filename)
+ except (FileNotFoundError, TraversalError):
+ unresolved_path = None
loop = asyncio.get_running_loop()
return await loop.run_in_executor(
None, self._resolve_path_to_response, unresolved_path
@@ -681,6 +686,8 @@ class StaticResource(PrefixResource):
# Check for access outside the root directory. For follow symlinks, URI
# cannot traverse out, but symlinks can. Otherwise, no access outside
# root is permitted.
+ if unresolved_path is None:
+ raise HTTPNotFound()
try:
if self._follow_symlinks:
normalized_path = Path(os.path.normpath(unresolved_path))
|