Serve files from a directory. Args: uri (str): The URI to serve the files at. directory (Path): The directory to serve files from. directory_view (bool): Whether to show a directory listing or not. index (str | Sequence[str] | None): The index file(s) to
| 32 | |
| 33 | |
| 34 | class DirectoryHandler: |
| 35 | """Serve files from a directory. |
| 36 | |
| 37 | Args: |
| 38 | uri (str): The URI to serve the files at. |
| 39 | directory (Path): The directory to serve files from. |
| 40 | directory_view (bool): Whether to show a directory listing or not. |
| 41 | index (str | Sequence[str] | None): The index file(s) to |
| 42 | serve if the directory is requested. Defaults to None. |
| 43 | root_path (Optional[Path]): The root path for security checks. |
| 44 | Symlinks resolving outside this path will be hidden from |
| 45 | directory listings. Defaults to directory if not specified. |
| 46 | follow_external_symlink_files (bool): Whether to show file symlinks |
| 47 | pointing outside root in directory listings. Defaults to False. |
| 48 | follow_external_symlink_dirs (bool): Whether to show directory symlinks |
| 49 | pointing outside root in directory listings. Defaults to False. |
| 50 | """ |
| 51 | |
| 52 | def __init__( |
| 53 | self, |
| 54 | uri: str, |
| 55 | directory: Path, |
| 56 | directory_view: bool = False, |
| 57 | index: str | Sequence[str] | None = None, |
| 58 | root_path: Path | None = None, |
| 59 | follow_external_symlink_files: bool = False, |
| 60 | follow_external_symlink_dirs: bool = False, |
| 61 | ) -> None: |
| 62 | if isinstance(index, str): |
| 63 | index = [index] |
| 64 | elif index is None: |
| 65 | index = [] |
| 66 | self.base = uri.strip("/") |
| 67 | self.directory = directory |
| 68 | self.directory_view = directory_view |
| 69 | self.index = tuple(index) |
| 70 | self.root_path = root_path if root_path is not None else directory |
| 71 | self.follow_external_symlink_files = follow_external_symlink_files |
| 72 | self.follow_external_symlink_dirs = follow_external_symlink_dirs |
| 73 | |
| 74 | async def handle(self, request: Request, path: str): |
| 75 | """Handle the request. |
| 76 | |
| 77 | Args: |
| 78 | request (Request): The incoming request object. |
| 79 | path (str): The path to the file to serve. |
| 80 | |
| 81 | Raises: |
| 82 | NotFound: If the file is not found. |
| 83 | IsADirectoryError: If the path is a directory and directory_view is False. |
| 84 | |
| 85 | Returns: |
| 86 | Response: The response object. |
| 87 | """ # noqa: E501 |
| 88 | current = unquote(path).strip("/")[len(self.base) :].strip("/") # noqa: E203 |
| 89 | for file_name in self.index: |
| 90 | index_file = self.directory / current / file_name |
| 91 | if index_file.is_file(): |
no outgoing calls
searching dependent graphs…