From a04f5e66916e954acea350e80303c587121f7a98 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 21 Oct 2026 19:53:41 +0000 Subject: [PATCH 1/2] build(deps): bump fastapi in /api in the pip-minor-and-patch group Bumps the pip-minor-and-patch group in /api with 1 update: [fastapi](https://github.com/fastapi/fastapi). Updates `fastapi` from 0.143.3 to 0.146.0 - [Release notes](https://github.com/fastapi/fastapi/releases) - [Commits](https://github.com/fastapi/fastapi/compare/0.143.3...0.146.0) --- updated-dependencies: - dependency-name: fastapi dependency-version: 0.146.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: pip-minor-and-patch ... Signed-off-by: dependabot[bot] --- api/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/requirements.txt b/api/requirements.txt index 0671b90..15c0bb5 100644 --- a/api/requirements.txt +++ b/api/requirements.txt @@ -1,4 +1,4 @@ # Pinned for reproducible builds; not fastapi[standard] (unneeded extras). -fastapi==0.143.3 +fastapi==0.146.0 uvicorn[standard]==0.54.0 PyJWT==2.15.1 From abb97b39fffcc463137c04fc273e74247c8c2344 Mon Sep 17 00:00:00 2001 From: Pol Alzina Date: Mon, 26 Oct 2026 12:49:59 +0100 Subject: [PATCH 2/2] Replace FastAPI's deprecated root_path with an /api route prefix FastAPI 0.146 deprecates the root_path parameter. nginx forwards /api/ unchanged, so give the health route its /api prefix directly; the tests now call the same paths production uses. /healthz and /api/health behave as before. Co-Authored-By: Claude Opus 5.5 --- api/main.py | 8 +++++--- tests/test_main.py | 12 ++++++------ 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/api/main.py b/api/main.py index 3ca0cbe..810508a 100644 --- a/api/main.py +++ b/api/main.py @@ -37,8 +37,10 @@ def load_version() -> str: _EXPOSE_STATS = os.getenv("FILESYNC_EXPOSE_STATS") == "1" # Init FastAPI. The interactive docs and OpenAPI schema are off: the HTTP surface is just -# /health, and the schema would only map the attack surface for a scanner. -app = FastAPI(title='FileSync API', version=load_version(), root_path="/api", +# /api/health, and the schema would only map the attack surface for a scanner. +# nginx forwards /api/ unchanged, so routes carry the prefix themselves (FastAPI's +# root_path parameter is deprecated). +app = FastAPI(title='FileSync API', version=load_version(), docs_url=None, redoc_url=None, openapi_url=None) # The signaling socket signs TURN credentials and reports the version on 'registered'. @@ -58,7 +60,7 @@ def load_version() -> str: ) # Add health check route: liveness, plus signaling capacity when FILESYNC_EXPOSE_STATS=1. -@app.get("/health") +@app.get("/api/health") async def health_check(): if _EXPOSE_STATS: return {"status": "ok", **registry_stats()} diff --git a/tests/test_main.py b/tests/test_main.py index 68c0cb9..82981a3 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -31,23 +31,23 @@ def main(monkeypatch): class TestHealth: def test_health_is_minimal_by_default(self, main): - r = TestClient(main.app).get("/health") + r = TestClient(main.app).get("/api/health") assert r.status_code == 200 assert r.json() == {"status": "ok"} def test_health_stats_are_opt_in(self, monkeypatch): main = _load_main(monkeypatch, FILESYNC_EXPOSE_STATS="1") - body = TestClient(main.app).get("/health").json() + body = TestClient(main.app).get("/api/health").json() assert body["status"] == "ok" assert set(body) == {"status", "registered_peers", "claims", "connections", "max_connections"} def test_other_values_do_not_expose_stats(self, monkeypatch): main = _load_main(monkeypatch, FILESYNC_EXPOSE_STATS="true") - assert TestClient(main.app).get("/health").json() == {"status": "ok"} + assert TestClient(main.app).get("/api/health").json() == {"status": "ok"} class TestRemovedSurface: - @pytest.mark.parametrize("path", ["/", "/uuid", "/credentials"]) + @pytest.mark.parametrize("path", ["/", "/api/uuid", "/api/credentials"]) def test_removed_routes_404(self, main, path): assert TestClient(main.app).get(path).status_code == 404 @@ -109,12 +109,12 @@ def test_startup_configures_signaling(self, main): class TestCors: def test_cors_off_by_default(self, main): - r = TestClient(main.app).get("/health", headers={"Origin": "http://localhost:5173"}) + r = TestClient(main.app).get("/api/health", headers={"Origin": "http://localhost:5173"}) assert "access-control-allow-origin" not in r.headers def test_cors_origins(self, monkeypatch): main = _load_main(monkeypatch, CORS_ORIGINS="http://localhost:5173, ") - r = TestClient(main.app).get("/health", headers={"Origin": "http://localhost:5173"}) + r = TestClient(main.app).get("/api/health", headers={"Origin": "http://localhost:5173"}) assert r.headers["access-control-allow-origin"] == "http://localhost:5173"