Health Score updation

This commit is contained in:
sriram
2026-09-04 17:55:13 +05:30
parent bb30edaffa
commit 0c36628d4b
2 changed files with 136 additions and 1 deletions

View File

@@ -27,7 +27,13 @@ PORTS=3000,8000
# Both spellings are listed so this keeps working if the typo is ever corrected
# in Dokploy. Exact origins, never a wildcard: the app sends an Authorization
# header, and browsers reject credentialed requests to a wildcard origin.
API_CORS_ORIGINS=https://catalouge.nearle.ai.in,https://catalogue.nearle.ai.in
#
# app.nearledaily.com is the merchant console, which calls /api/nutrition/*
# from the browser. Until it was listed here every one of those calls failed
# as an opaque "Failed to fetch" while curl returned 200 - the server saw a
# healthy request and the browser discarded the response. localhost:3100 is
# that console in local development.
API_CORS_ORIGINS=https://catalouge.nearle.ai.in,https://catalogue.nearle.ai.in,https://app.nearledaily.com,http://localhost:3100
# --- Authentication --------------------------------------------------------
AUTH_ENABLED=true

129
tests/test_cors_origins.py Normal file
View File

@@ -0,0 +1,129 @@
"""The browser is the only client that enforces CORS, and no test here is one.
THE FAILURE THIS FILE EXISTS FOR
--------------------------------
The merchant console called `https://mcp.nearle.ai.in/api/...` from Chrome and got
`TypeError: Failed to fetch` for a whole day. The same URL under curl returned 200
with the right body, so every server-side check - ours and theirs - passed. The
response carried `Access-Control-Allow-Credentials: true` and no
`Access-Control-Allow-Origin`, and the browser discarded it before any code saw it.
The cause was not missing middleware. `CORSMiddleware` was installed and correct;
the console's origin was simply not in `API_CORS_ORIGINS`, so Starlette declined to
echo the header. Nothing in the server log looked wrong: a healthy 200, every time.
That is why the deployed allowlist is asserted as DATA below. A unit test cannot
fail the way a browser fails, so the next best thing is to pin the one value whose
absence produces a silent, total outage for a first-party client.
"""
from __future__ import annotations
import re
from pathlib import Path
import pytest
ENV_PRODUCTION = Path(__file__).resolve().parents[1] / ".env.production"
# Every first-party browser client of this API. A new one added to the console
# and not added here is the bug above, repeated.
REQUIRED_ORIGINS = (
"https://app.nearledaily.com", # merchant console
"http://localhost:3100", # merchant console, local development
"https://catalogue.nearle.ai.in", # catalogue frontend
)
def _deployed_origins():
"""The allowlist the image ships with.
Read from the file rather than from `settings`, because the test process has
its own environment - importing the setting would assert on the developer's
machine instead of on what gets deployed.
"""
if not ENV_PRODUCTION.exists():
pytest.skip(".env.production is not present in this checkout")
for line in ENV_PRODUCTION.read_text(encoding="utf-8").splitlines():
line = line.strip()
if line.startswith("API_CORS_ORIGINS="):
value = line.split("=", 1)[1]
return [o.strip() for o in value.split(",") if o.strip()]
return []
@pytest.mark.parametrize("origin", REQUIRED_ORIGINS)
def test_every_first_party_browser_client_is_allowed(origin):
assert origin in _deployed_origins(), (
"%s is missing from API_CORS_ORIGINS in .env.production. Browser calls "
"from it fail as an opaque 'Failed to fetch' while curl still returns "
"200, so nothing server-side will catch this." % origin
)
def test_the_allowlist_is_not_a_wildcard():
"""A wildcard would disable `allow_credentials` (see the guard in main.py),
silently breaking any authenticated browser call to this API."""
assert "*" not in _deployed_origins()
def test_every_origin_is_a_bare_scheme_and_host():
"""An Origin header is scheme + host + port, never a path and never a
trailing slash. `https://app.nearledaily.com/` does not match and fails
exactly as if it were absent."""
for origin in _deployed_origins():
assert re.fullmatch(r"https?://[A-Za-z0-9.\-]+(:\d+)?", origin), origin
# ---------------------------------------------------------------------------
# The middleware itself
# ---------------------------------------------------------------------------
# These run against whatever origins the TEST environment carries, so they pin
# the behaviour rather than the deployed list: an allowed origin is echoed, an
# unknown one is not, and a preflight from an unknown origin is refused.
def _allowed_origin():
from app.infrastructure.settings import API_CORS_ORIGINS
if not API_CORS_ORIGINS:
pytest.skip("no CORS origins configured in the test environment")
return API_CORS_ORIGINS[0]
def test_an_allowed_origin_is_echoed_back(client):
origin = _allowed_origin()
response = client.get("/api/health", headers={"Origin": origin})
assert response.headers.get("access-control-allow-origin") == origin
def test_an_unknown_origin_gets_no_header_at_all(client):
"""The response still returns 200 with a correct body - which is why this is
invisible everywhere except a browser."""
response = client.get("/api/health", headers={"Origin": "https://not-listed.example"})
assert response.status_code == 200
assert "access-control-allow-origin" not in response.headers
def test_a_preflight_from_an_allowed_origin_succeeds(client):
response = client.options(
"/api/health",
headers={"Origin": _allowed_origin(),
"Access-Control-Request-Method": "GET",
"Access-Control-Request-Headers": "content-type"},
)
assert response.status_code == 200
assert response.headers.get("access-control-allow-origin") == _allowed_origin()
def test_a_preflight_from_an_unknown_origin_is_refused(client):
"""Starlette answers 400 here. It reads as a malformed request in the log,
which is how this was mistaken for a second, unrelated bug."""
response = client.options(
"/api/health",
headers={"Origin": "https://not-listed.example",
"Access-Control-Request-Method": "GET"},
)
assert response.status_code == 400