test_spa_404.py 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. """SPA 静态托管 404 收敛(安全)。
  2. 合法 URL/API 之外的未知路径一律 404:前端无路径路由(仅 query 传参),
  3. SPA 回退仅覆盖根路径 /;已注册 API 与存在的静态文件照常响应。
  4. """
  5. from __future__ import annotations
  6. import pytest
  7. @pytest.fixture()
  8. def spa_client(flask_app, tmp_path, monkeypatch):
  9. """临时 dist(index.html + assets/app.js),不依赖开发机构建产物。"""
  10. (tmp_path / "index.html").write_text("<html>index</html>", encoding="utf-8")
  11. assets = tmp_path / "assets"
  12. assets.mkdir()
  13. (assets / "app.js").write_text("console.log(1)", encoding="utf-8")
  14. import app as app_module
  15. monkeypatch.setattr(app_module, "FRONTEND_DIST", tmp_path)
  16. return flask_app.test_client()
  17. def test_root_serves_index(spa_client):
  18. response = spa_client.get("/")
  19. assert response.status_code == 200
  20. assert b"index" in response.data
  21. def test_existing_asset_served(spa_client):
  22. assert spa_client.get("/assets/app.js").status_code == 200
  23. def test_health_still_ok(spa_client):
  24. assert spa_client.get("/api/health").status_code == 200
  25. @pytest.mark.parametrize(
  26. "path",
  27. [
  28. "/admin.php",
  29. "/wp-login",
  30. "/index2.html",
  31. "/.env",
  32. "/api/v1/not-implemented",
  33. "/api/v2/evil",
  34. # 畸形路径字符(Windows 非法字符、NUL):不得异常,统一 404
  35. "/%3Cscript%3E",
  36. "/a|b",
  37. "/c:d",
  38. "/%00",
  39. ],
  40. )
  41. def test_unknown_paths_return_404(spa_client, path):
  42. response = spa_client.get(path)
  43. assert response.status_code == 404