fix: add CORS middleware for cross-origin image serving #12
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "11-add-cors-middleware"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
minio-api had zero CORS configuration, causing browsers to block cross-origin image requests via Opaque Response Blocking (ORB). Added
CORSMiddlewarewith configurable origins viaCORS_ALLOWED_ORIGINSenv var, scoped to read-only methods.Changes
src/minio_api/main.py— AddedCORSMiddlewarewith default origins for westside, pal-e-app, and mcd-tracker. Configurable viaCORS_ALLOWED_ORIGINSenv var (comma-separated). Only allows GET/HEAD/OPTIONS since this is a read-heavy asset server.Review Checklist
Test Plan
Access-Control-Allow-Originheader present on responses whenOriginheader sentCORS_ALLOWED_ORIGINS=https://example.comenv varRelated
Related Notes
src/basketball_api/main.pyPR #12 Review
DOMAIN REVIEW
Tech stack: Python / FastAPI / Starlette CORSMiddleware
This PR adds CORS middleware configuration to
src/minio_api/main.py. The change is 22 lines (all additions), confined to a single file.CORS configuration analysis:
westsidekingsandqueens,pal-e-app,mcd-tracker-- all on.tail5b443a.ts.net). No wildcard*. Overridable viaCORS_ALLOWED_ORIGINSenv var (comma-separated). Correct.["GET", "HEAD", "OPTIONS"]-- appropriate for a read-only asset server. Does not expose PUT/POST/DELETE to cross-origin callers. Correct.allow_credentials=False-- correct since no cookies/auth tokens needed for image serving. (Note: basketball-api usesTruebecause it has auth -- this distinction is intentional and correct.)allow_headers=["*"]-- consistent with the basketball-api ecosystem pattern. For a read-only asset server this is acceptable; the method restriction is the meaningful security boundary.Pattern consistency: Follows the established basketball-api CORS pattern from
/home/ldraney/basketball-api/src/basketball_api/main.pylines 52-63, with appropriate tightening (credentials=False, methods restricted).BLOCKERS
None.
Test coverage assessment: This PR has zero CORS-specific tests. However, this is a configuration-only change -- a 6-line
app.add_middleware()call using Starlette's well-testedCORSMiddleware. The origin-parsing logic (lines 22-27) is the only custom code and is trivially correct. All 63 existing tests continue to pass through the middleware layer. This does not meet the "new functionality with zero test coverage" blocker threshold because no new business logic or code paths were introduced.NITS
allow_headers=["*"]could be tightened: For a read-only asset server, the only headers browsers typically send on cross-origin image/fetch requests are standard simple headers. You could restrict to["Accept", "Accept-Language", "Content-Language", "Range"]instead of["*"]. However,["*"]is the ecosystem convention (matches basketball-api) and the method restriction is the meaningful security boundary. Non-blocking.Module-level
os.getenvat import time: The_raw_originsvariable (line 22) is evaluated at import time, which means changing the env var after import has no effect. This is the standard FastAPI pattern and is fine for production (env vars are set before process start), but worth noting for test scenarios that might want to override origins via monkeypatch. The current test suite does not test CORS so this is not a problem today.Future consideration -- CORS integration test: A single test asserting that an
OPTIONSpreflight from a known origin returnsAccess-Control-Allow-Originwould be valuable for regression confidence. Not blocking this PR, but worth tracking.SOP COMPLIANCE
11-add-cors-middlewarematches issue #11Closes #11fix: add CORS middleware for cross-origin image servingis clearPROCESS OBSERVATIONS
GET/HEAD/OPTIONSonly) limits blast radius. Rollback is trivial (remove middleware).ERR_BLOCKED_BY_ORBthat would otherwise require per-consumer workarounds.CORS_ALLOWED_ORIGINSis self-documenting via the code defaults. A README note about the override mechanism would be helpful but is not blocking.VERDICT: APPROVED