def test_serve_file_options_raise_for_invalid_path(): with pytest.raises(InvalidArgument): ServeFilesOptions("./not-existing").validate() with pytest.raises(InvalidArgument): ServeFilesOptions(files2_index_path).validate()
async def test_static_files_support_authentication_by_route(): app = FakeApplication() app.use_authentication().add(MockNotAuthHandler()) app.use_authorization().add( AdminsPolicy()).default_policy += AuthenticatedRequirement() @app.router.get("/") async def home(): return None app.serve_files( ServeFilesOptions(get_folder_path("files"), allow_anonymous=False)) app.serve_files( ServeFilesOptions(get_folder_path("files2"), allow_anonymous=True, root_path="/login")) await app.start() await app(get_example_scope("GET", "/"), MockReceive(), MockSend()) assert app.response.status == 401 await app(get_example_scope("GET", "/lorem-ipsum.txt"), MockReceive(), MockSend()) assert app.response.status == 401 await app(get_example_scope("GET", "/login/index.html"), MockReceive(), MockSend()) assert app.response.status == 200 content = await app.response.text() assert (content == """<!DOCTYPE html> <html> <head> <title>Example.</title> <link rel="stylesheet" type="text/css" href="/styles/main.css" /> </head> <body> <h1>Lorem ipsum</h1> <p>Dolor sit amet.</p> <script src="/scripts/main.js"></script> </body> </html> """)
async def test_static_files_support_authentication(): app = FakeApplication() app.use_authentication().add(MockNotAuthHandler()) app.use_authorization().add( AdminsPolicy()).default_policy += AuthenticatedRequirement() @app.router.get("/") async def home(): return None app.serve_files( ServeFilesOptions(get_folder_path("files"), allow_anonymous=False)) await app.start() await app(get_example_scope("GET", "/"), MockReceive(), MockSend()) assert app.response.status == 401 await app(get_example_scope("GET", "/lorem-ipsum.txt"), MockReceive(), MockSend()) assert app.response.status == 401
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(ServeFilesOptions(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_serve_files_deprecated_serve_files_options( files2_index_contents, app, mock_receive, mock_send): 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, mock_receive(), mock_send, ) response = app.response assert response.status == 200 assert files2_index_contents == await response.read()
async def test_cannot_serve_files_outside_static_folder(): app = FakeApplication() folder_path = get_folder_path("files") options = ServeFilesOptions(folder_path, discovery=True, extensions={".py"}) app.serve_files(options) 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_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_fallback_document(files2_index_contents: bytes): """Feature used to serve SPAs that use HTML5 History API""" app = FakeApplication() app.serve_files( ServeFilesOptions(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_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_custom_index_page(): app = FakeApplication() # Note the folder files3 does not contain an index.html page app.serve_files( ServeFilesOptions(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()
from blacksheep.server.bindings import FromQuery from blacksheep.server.files import ServeFilesOptions from blacksheep.server.responses import ContentDispositionType, file, json, text from itests.utils import CrashTest, ensure_folder app = Application(show_error_details=True) static_folder_path = pathlib.Path(__file__).parent.absolute() / "static" def get_static_path(file_name): static_folder_path = pathlib.Path(__file__).parent.absolute() / "static" return os.path.join(str(static_folder_path), file_name) app.serve_files(ServeFilesOptions(static_folder_path, discovery=True)) @app.route("/hello-world") async def hello_world(): return text(f"Hello, World!") @app.router.head("/echo-headers") async def echo_headers(request): response = Response(200) for header in request.headers: response.add_header(header[0], header[1]) return response
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