async def test_serve_files_with_custom_files_handler(): app = FakeApplication() file_path = files2_index_path with open(file_path, mode="rt") as actual_file: expected_body = actual_file.read() class CustomFilesHandler(FilesHandler): def __init__(self) -> None: self.calls = [] def open(self, file_path: str, mode: str = "rb") -> FileContext: self.calls.append(file_path) return super().open(file_path, mode) app.files_handler = CustomFilesHandler() folder_path = get_folder_path("files2") app.serve_files(ServeFilesOptions(folder_path, discovery=True)) await app.start() scope = get_example_scope("GET", "/index.html", []) await app( scope, MockReceive(), MockSend(), ) response = app.response assert response.status == 200 body = await response.text() assert body == expected_body assert app.files_handler.calls[0] == file_path
async def test_serve_files_discovery(folder_name: str): app = FakeApplication() folder_path = get_folder_path(folder_name) options = ServeFilesOptions(folder_path, discovery=True) app.serve_files(options) await app.start() scope = get_example_scope("GET", "/", []) await app( scope, MockReceive(), MockSend(), ) response = app.response assert response.status == 200 body = await response.text() folder = Path(folder_path) for item in folder.iterdir(): if item.is_dir(): assert f"/{item.name}" in body continue file_extension = get_file_extension(str(item)) if file_extension in options.extensions: assert f"/{item.name}" in body else: assert item.name not in body
async def test_serve_files_can_disable_index_html_by_default(): app = FakeApplication() app.serve_files(get_folder_path("files2"), index_document=None) await app.start() scope = get_example_scope("GET", "/", []) await app( scope, MockReceive(), MockSend(), ) response = app.response assert response.status == 404
async def test_serve_files_serves_index_html_by_default(files2_index_contents): app = FakeApplication() app.serve_files(ServeFilesOptions(get_folder_path("files2"))) await app.start() scope = get_example_scope("GET", "/", []) await app( scope, MockReceive(), MockSend(), ) response = app.response assert response.status == 200 assert files2_index_contents == await response.read()
async def test_serve_files_no_discovery(): app = FakeApplication() # Note the folder files3 does not contain an index.html page app.serve_files(ServeFilesOptions(get_folder_path("files3"))) await app.start() scope = get_example_scope("GET", "/", []) await app( scope, MockReceive(), MockSend(), ) response = app.response assert response.status == 404
async def test_cannot_serve_files_with_unhandled_extension(): app = FakeApplication() folder_path = get_folder_path("files2") app.serve_files(folder_path, discovery=True, extensions={".py"}) await app.start() scope = get_example_scope("GET", "/example.config", []) await app( scope, MockReceive(), MockSend(), ) response = app.response assert response.status == 404
async def test_cannot_serve_files_outside_static_folder(): app = FakeApplication() folder_path = get_folder_path("files") app.serve_files(folder_path, discovery=True, extensions={".py"}) await app.start() scope = get_example_scope("GET", "../test_files_serving.py", []) await app( scope, MockReceive(), MockSend(), ) response = app.response assert response.status == 404
async def test_serve_files_deprecated_serve_files_options(files2_index_contents): app = FakeApplication() with pytest.deprecated_call(): app.serve_files(ServeFilesOptions(get_folder_path("files2"))) # type: ignore await app.start() scope = get_example_scope("GET", "/", []) await app( scope, MockReceive(), MockSend(), ) response = app.response assert response.status == 200 assert files2_index_contents == await response.read()
async def test_serve_files_fallback_document(files2_index_contents: bytes): """Feature used to serve SPAs that use HTML5 History API""" app = FakeApplication() app.serve_files(get_folder_path("files2"), fallback_document="index.html") await app.start() for path in {"/", "/one", "/one/two", "/one/two/anything.txt"}: scope = get_example_scope("GET", path, []) await app( scope, MockReceive(), MockSend(), ) response = app.response assert response.status == 200 assert await response.read() == files2_index_contents
async def test_can_serve_files_with_relative_paths(files2_index_contents): app = FakeApplication() folder_path = get_folder_path("files2") options = ServeFilesOptions(folder_path, discovery=True) app.serve_files(options) await app.start() scope = get_example_scope("GET", "/styles/../index.html", []) await app( scope, MockReceive(), MockSend(), ) response = app.response assert response.status == 200 body = await response.read() assert body == files2_index_contents scope = get_example_scope("GET", "/styles/fonts/../../index.html", []) await app( scope, MockReceive(), MockSend(), ) response = app.response assert response.status == 200 body = await response.read() assert body == files2_index_contents scope = get_example_scope("GET", "/styles/../does-not-exist.html", []) await app( scope, MockReceive(), MockSend(), ) response = app.response assert response.status == 404
async def test_serve_files_custom_index_page(): app = FakeApplication() # Note the folder files3 does not contain an index.html page app.serve_files(get_folder_path("files3"), index_document="lorem-ipsum.txt") await app.start() scope = get_example_scope("GET", "/", []) await app( scope, MockReceive(), MockSend(), ) response = app.response assert response.status == 200 with open(get_file_path("lorem-ipsum.txt", "files3"), mode="rt") as actual_file: content = actual_file.read() assert content == await response.text()
async def test_serve_files_discovery_subfolder(): app = FakeApplication() folder_path = get_folder_path("files2") app.serve_files(ServeFilesOptions(folder_path, discovery=True)) await app.start() scope = get_example_scope("GET", "/scripts", []) await app( scope, MockReceive(), MockSend(), ) response = app.response assert response.status == 200 body = await response.text() folder = Path(folder_path) / "scripts" for item in folder.iterdir(): assert f"/{item.name}" in body
async def test_serve_files_multiple_folders(files2_index_contents): app = FakeApplication() files1 = get_folder_path("files") files2 = get_folder_path("files2") app.serve_files(ServeFilesOptions(files1, discovery=True, root_path="one")) app.serve_files(ServeFilesOptions(files2, discovery=True, root_path="two")) await app.start() scope = get_example_scope("GET", "/", []) await app( scope, MockReceive(), MockSend(), ) assert app.response.status == 404 scope = get_example_scope("GET", "/example.txt", []) await app( scope, MockReceive(), MockSend(), ) assert app.response.status == 404 scope = get_example_scope("GET", "/one/example.txt", []) await app( scope, MockReceive(), MockSend(), ) response = app.response assert response.status == 200 body = await response.read() with open(get_file_path("example.txt"), mode="rb") as actual_file: assert body == actual_file.read() scope = get_example_scope("GET", "/two/styles/main.css", []) await app( scope, MockReceive(), MockSend(), ) response = app.response assert response.status == 200 body = await response.read() with open(get_file_path("styles/main.css", "files2"), mode="rb") as actual_file: assert body == actual_file.read() scope = get_example_scope("GET", "/two/index.html", []) await app( scope, MockReceive(), MockSend(), ) response = app.response assert response.status == 200 body = await response.read() assert body == files2_index_contents