async def test_session_middleware_with_encryptor(app, mock_receive, mock_send): app.middlewares.append( SessionMiddleware("LOREM_IPSUM", encryptor=FernetEncryptor(Fernet.generate_key()))) @app.router.get("/") def home(request: Request): session = request.session assert isinstance(session, Session) session["foo"] = "Some value" return text("Hello, World") @app.router.get("/second") def second(request: Request): session = request.session assert "foo" in session assert session["foo"] == "Some value" return text("Hello, World") await app.start() await app( get_example_scope( "GET", "/", ), mock_receive(), mock_send, ) response = app.response assert response.status == 200 session_set_cookie = response.headers.get_single(b"Set-Cookie") assert session_set_cookie is not None cookie = parse_cookie(session_set_cookie) await app( get_example_scope( "GET", "/second", [ [b"cookie", b"session=" + cookie.value.encode()], ], ), mock_receive(), mock_send, ) response = app.response assert response.status == 200 session_set_cookie = response.headers.get_first(b"Set-Cookie") assert session_set_cookie is None
async def test_session_middleware_handling_of_expired_signature( app, mock_receive, mock_send): app.middlewares.append(SessionMiddleware("LOREM_IPSUM", session_max_age=1)) @app.router.get("/") def home(request: Request): session = request.session assert isinstance(session, Session) session["foo"] = "Some value" return text("Hello, World") @app.router.get("/second") def second(request: Request): session = request.session assert "foo" not in session return text("Hello, World") await app.start() await app( get_example_scope( "GET", "/", ), mock_receive(), mock_send, ) response = app.response assert response.status == 200 session_set_cookie = response.headers.get_single(b"Set-Cookie") assert session_set_cookie is not None cookie = parse_cookie(session_set_cookie) time.sleep(2) await app( get_example_scope( "GET", "/second", [ [b"cookie", b"session=" + cookie.value.encode()], ], ), mock_receive(), mock_send, ) response = app.response assert response.status == 200 session_set_cookie = response.headers.get_first(b"Set-Cookie") assert session_set_cookie is None
async def test_pretty_json_response_in_controller(obj: Any, values: Dict[str, Any], app, mock_receive, mock_send): app.controllers_router = RoutesRegistry() get = app.controllers_router.get class Home(Controller): @get("/") def greet(self): return self.pretty_json(obj) await app.start() await app( get_example_scope("GET", "/", []), mock_receive(), mock_send, ) response = app.response raw = await response.text() assert response.status == 200 content_type = response.headers.get_single(b"content-type") assert content_type == b"application/json" raw = await response.text() data = await response.json() for name, value in values.items(): assert data.get(name) == value if isinstance(value, str): assert f' "{name}": "{value}"' in raw else: assert f' "{name}": ' in raw
async def test_created_response_with_value(app, mock_receive, mock_send): @app.router.get("/") async def home(): return created( Foo(UUID("726807b3-5a82-4a59-8bed-65639d3529ba"), "example", False), location="https://foo.org/foo/726807b3-5a82-4a59-8bed-65639d3529ba", ) app.normalize_handlers() await app( get_example_scope("GET", "/", []), mock_receive(), mock_send, ) response = app.response assert response.status == 201 location = response.headers.get_single(b"location") assert location == b"https://foo.org/foo/726807b3-5a82-4a59-8bed-65639d3529ba" content = await app.response.json() assert content.get("id") == "726807b3-5a82-4a59-8bed-65639d3529ba" assert content.get("name") == "example" assert content.get("ufo") is False
async def test_status_method_response_in_controller(method, expected_status, app, mock_receive, mock_send): app.controllers_router = RoutesRegistry() get = app.controllers_router.get method_name = method.__name__ class Home(Controller): @get("/") def greet(self): controller_method = getattr(Home, method_name, None) return controller_method(self, "Everything's good") controller_method = getattr(Home, method_name, None) assert callable(controller_method) await app.start() await app( get_example_scope("GET", "/", []), mock_receive(), mock_send, ) assert app.response.status == expected_status content = await app.response.text() assert content == "Everything's good"
async def test_redirect_method_in_controller(method, expected_status, app, mock_receive, mock_send): app.controllers_router = RoutesRegistry() get = app.controllers_router.get method_name = method.__name__ class Home(Controller): @get("/") def greet(self): controller_method = getattr(Home, method_name, None) return controller_method(self, "https://foo.org/somewhere") controller_method = getattr(Home, method_name, None) assert callable(controller_method) await app.start() await app( get_example_scope("GET", "/", []), mock_receive(), mock_send, ) response = app.response assert response.status == expected_status location = response.headers.get_single(b"location") assert location == b"https://foo.org/somewhere"
async def test_file_response_from_bytes_io(app, mock_receive, mock_send): bytes_io: Optional[BytesIO] = None @app.router.get("/") async def home(): nonlocal bytes_io bytes_io = BytesIO() bytes_io.write("Żywią i bronią".encode("utf-8")) return file(bytes_io, "text/plain; charset=utf-8", file_name="foo.txt") app.normalize_handlers() await app( get_example_scope("GET", "/", []), mock_receive(), mock_send, ) response = app.response assert response.status == 200 assert response.headers.get_single( b"content-type") == b"text/plain; charset=utf-8" assert (response.headers.get_single(b"content-disposition") == b'attachment; filename="foo.txt"') assert bytes_io is not None assert bytes_io.closed # type: ignore
async def test_file_response_from_fs_with_filename(app, mock_receive, mock_send): file_path = get_file_path("example.config", "files2") @app.router.get("/") async def home(): return file(file_path, "text/plain; charset=utf-8", file_name="foo.xml") app.normalize_handlers() await app( get_example_scope("GET", "/", []), mock_receive(), mock_send, ) response = app.response assert response.status == 200 assert response.headers.get_single( b"content-type") == b"text/plain; charset=utf-8" assert (response.headers.get_single(b"content-disposition") == b'attachment; filename="foo.xml"') text = await response.text() with open(file_path, mode="rt", encoding="utf8") as f: contents = f.read() assert contents == text
async def test_status_method_without_body_response_in_controller( method, expected_status, app, mock_receive, mock_send): app.controllers_router = RoutesRegistry() get = app.controllers_router.get method_name = method.__name__ class Home(Controller): @get("/") def greet(self): controller_method = getattr(Home, method_name, None) return controller_method(self) controller_method = getattr(Home, method_name, None) assert callable(controller_method) await app.start() await app( get_example_scope("GET", "/", []), mock_receive(), mock_send, ) response = app.response assert response.status == expected_status assert response.has_body() is False
async def test_file_response_from_byte_array(app, mock_receive, mock_send): value = bytearray() value.extend(b"Hello!\n") value.extend(b"World!\n\n") value.extend(b"...") expected_result = bytes(value).decode("utf8") @app.router.get("/") async def home(): return file( value, "text/plain", file_name="example.txt", content_disposition=ContentDispositionType.INLINE, ) app.normalize_handlers() await app( get_example_scope("GET", "/", []), mock_receive(), mock_send, ) response = app.response assert response.status == 200 assert response.headers.get_single(b"content-type") == b"text/plain" assert (response.headers.get_single(b"content-disposition") == b'inline; filename="example.txt"') text = await response.text() assert text == expected_result
async def test_file_response_from_generator_inline_with_name( app, mock_receive, mock_send): @app.router.get("/") async def home(): return file( get_example_css, "text/css", file_name="home.css", content_disposition=ContentDispositionType.INLINE, ) app.normalize_handlers() await app( get_example_scope("GET", "/", []), mock_receive(), mock_send, ) response = app.response assert response.status == 200 assert response.headers.get_single(b"content-type") == b"text/css" assert (response.headers.get_single(b"content-disposition") == b'inline; filename="home.css"') text = await response.text() assert text == await read_from_asynciterable(get_example_css)
async def test_pretty_json_response(obj: Any, values: Dict[str, Any], app, mock_receive, mock_send): @app.router.get("/") async def home(): return pretty_json(obj) app.normalize_handlers() await app( get_example_scope("GET", "/", []), mock_receive(), mock_send, ) response = app.response assert response.status == 200 content_type = response.headers.get_single(b"content-type") assert content_type == b"application/json" raw = await response.text() data = await response.json() for name, value in values.items(): assert data.get(name) == value if isinstance(value, str): assert f' "{name}": "{value}"' in raw else: assert f' "{name}": ' in raw
async def _view_scenario(app: FakeApplication, expected_text, url="/"): app.build_services() app.normalize_handlers() await app(get_example_scope("GET", url), MockReceive(), MockSend()) text = await app.response.text() assert text == expected_text assert app.response.status == 200
async def test_serve_files_with_custom_files_handler(app, mock_receive, mock_send): 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(folder_path, discovery=True) await app.start() scope = get_example_scope("GET", "/index.html", []) await app( scope, mock_receive(), mock_send, ) 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, mock_receive, mock_send): folder_path = get_folder_path(folder_name) app.serve_files(folder_path, discovery=True) extensions = get_default_extensions() await app.start() scope = get_example_scope("GET", "/", []) await app( scope, mock_receive(), mock_send, ) 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 extensions: assert f"/{item.name}" in body else: assert item.name not in body
async def test_static_files_support_authentication_by_route( app, mock_receive, mock_send ): app.use_authentication().add(MockNotAuthHandler()) app.use_authorization().add( AdminsPolicy() ).default_policy += AuthenticatedRequirement() @app.router.get("/") async def home(): return None app.serve_files(get_folder_path("files"), allow_anonymous=False) app.serve_files(get_folder_path("files2"), allow_anonymous=True, root_path="/login") await app.start() await app(get_example_scope("GET", "/"), mock_receive(), mock_send) assert app.response.status == 401 await app(get_example_scope("GET", "/lorem-ipsum.txt"), mock_receive(), mock_send) assert app.response.status == 401 await app(get_example_scope("GET", "/login/index.html"), mock_receive(), mock_send) 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_can_serve_files_with_relative_paths(files2_index_contents, app, mock_receive, mock_send): folder_path = get_folder_path("files2") app.serve_files(folder_path, discovery=True) await app.start() scope = get_example_scope("GET", "/styles/../index.html", []) await app( scope, mock_receive(), mock_send, ) 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, mock_receive(), mock_send, ) 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, mock_receive(), mock_send, ) response = app.response assert response.status == 404
async def test_static_files_support_authentication(app, mock_receive, mock_send): app.use_authentication().add(MockNotAuthHandler()) app.use_authorization().add( AdminsPolicy() ).default_policy += AuthenticatedRequirement() @app.router.get("/") async def home(): return None app.serve_files(get_folder_path("files"), allow_anonymous=False) await app.start() await app(get_example_scope("GET", "/"), mock_receive(), mock_send) assert app.response.status == 401 await app(get_example_scope("GET", "/lorem-ipsum.txt"), mock_receive(), mock_send) assert app.response.status == 401
async def test_authorization_default_requires_authenticated_user( app, mock_receive, mock_send ): app.use_authentication().add(MockNotAuthHandler()) app.use_authorization() @app.router.get("/") async def home(): return None @auth() @app.router.get("/admin") async def admin(): return None app.prepare() await app(get_example_scope("GET", "/"), mock_receive(), mock_send) assert app.response.status == 204 await app(get_example_scope("GET", "/admin"), mock_receive(), mock_send) assert app.response.status == 401
async def test_authorization_default_allows_anonymous(app, mock_receive, mock_send): app.use_authentication().add(MockAuthHandler()) app.use_authorization().add(AdminsPolicy()) @app.router.get("/") async def home(): return None app.prepare() await app(get_example_scope("GET", "/"), mock_receive(), mock_send) assert app.response.status == 204
async def test_authorization_unauthorized_error(app, mock_receive, mock_send): app.use_authentication().add(MockAuthHandler()) app.use_authorization().add(AdminsPolicy()) @auth("admin") @app.router.get("/") async def home(): return None app.prepare() await app(get_example_scope("GET", "/"), mock_receive(), mock_send) assert app.response.status == 401
async def test_serve_files_no_discovery(app, mock_receive, mock_send): # Note the folder files3 does not contain an index.html page app.serve_files(get_folder_path("files3")) await app.start() scope = get_example_scope("GET", "/", []) await app( scope, mock_receive(), mock_send, ) response = app.response assert response.status == 404
async def test_serve_files_can_disable_index_html_by_default( app, mock_receive, mock_send): app.serve_files(get_folder_path("files2"), index_document=None) await app.start() scope = get_example_scope("GET", "/", []) await app( scope, mock_receive(), mock_send, ) response = app.response assert response.status == 404
async def test_authorization_policy_success(app, mock_receive, mock_send): admin = Identity({"id": "001", "name": "Charlie Brown", "role": "admin"}, "JWT") app.use_authentication().add(MockAuthHandler(admin)) app.use_authorization().add(AdminsPolicy()) @auth("admin") @app.router.get("/") async def home(): return None app.prepare() await app(get_example_scope("GET", "/"), mock_receive(), mock_send) assert app.response.status == 204
async def test_serve_files_serves_index_html_by_default( files2_index_contents, app, mock_receive, mock_send): app.serve_files(get_folder_path("files2")) 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_with_unhandled_extension( app, mock_receive, mock_send): 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, mock_receive(), mock_send, ) response = app.response assert response.status == 404
async def test_cannot_serve_files_outside_static_folder( app, mock_receive, mock_send): 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, mock_receive(), mock_send, ) response = app.response assert response.status == 404
async def test_status_code_response_with_empty_body(status: int, app, mock_receive, mock_send): @app.router.get("/") async def home(): return status_code(status) app.normalize_handlers() await app( get_example_scope("GET", "/", []), mock_receive(), mock_send, ) assert app.response.status == status content = await app.response.text() assert content == ""
async def test_status_method_response_empty_body(method, expected_status, app, mock_receive, mock_send): @app.router.get("/") async def home(): return method() app.normalize_handlers() await app( get_example_scope("GET", "/", []), mock_receive(), mock_send, ) assert app.response.status == expected_status content = await app.response.text() assert content == ""
async def test_created_response_with_empty_body(app, mock_receive, mock_send): @app.router.get("/") async def home(): return created(location="https://foo.org/foo/001") app.normalize_handlers() await app( get_example_scope("GET", "/", []), mock_receive(), mock_send, ) response = app.response assert response.status == 201 location = response.headers.get_single(b"location") assert location == b"https://foo.org/foo/001"