Files

88 lines
3.1 KiB
Python
Raw Permalink Normal View History

2026-01-08 01:00:26 +10:30
"""CORS middleware configuration."""
2026-01-08 15:59:53 +10:30
from flask import request, make_response
2026-01-08 01:00:26 +10:30
ALLOWED_METHODS = "GET, POST, PUT, PATCH, DELETE, OPTIONS"
ALLOWED_HEADERS = (
"Content-Type, Authorization, X-Requested-With, X-Request-ID, "
"Cache-Control, Pragma, X-WebAuthn-Session-Token"
)
def _is_origin_allowed(origin, cors_origins):
"""Return True if the origin is permitted by the CORS config.
Handles both wildcard ("*") and explicit origin lists.
"""
if not origin:
return False
if cors_origins == "*":
return True
if isinstance(cors_origins, list):
if "*" in cors_origins:
return True
return origin in cors_origins
return False
def _cors_origin_header(cors_origins, request_origin):
"""Return the value for Access-Control-Allow-Origin.
Per the CORS spec, browsers reject ``*`` when credentials are involved,
so we echo the request origin when wildcard + credentials is configured.
"""
allow_all = cors_origins == "*" or (isinstance(cors_origins, list) and "*" in cors_origins)
if allow_all and request_origin:
return request_origin
if allow_all:
return "*"
if request_origin and request_origin in cors_origins:
return request_origin
return None
2026-01-08 01:00:26 +10:30
2026-01-08 15:59:53 +10:30
def setup_cors(app):
2026-01-08 01:00:26 +10:30
"""
Configure CORS for the application.
Args:
app: Flask application instance
"""
supports_credentials = app.config.get("CORS_SUPPORTS_CREDENTIALS", True)
2026-01-08 15:59:53 +10:30
@app.before_request
def handle_preflight():
"""Handle CORS preflight OPTIONS requests."""
if request.method == "OPTIONS":
origin = request.headers.get("Origin")
cors_origins = app.config.get("CORS_ORIGINS", [])
if not _is_origin_allowed(origin, cors_origins):
return None
response = make_response("", 204)
response.headers["Access-Control-Allow-Origin"] = _cors_origin_header(cors_origins, origin)
response.headers["Access-Control-Allow-Methods"] = ALLOWED_METHODS
response.headers["Access-Control-Allow-Headers"] = ALLOWED_HEADERS
if supports_credentials:
2026-01-08 15:59:53 +10:30
response.headers["Access-Control-Allow-Credentials"] = "true"
response.headers["Access-Control-Max-Age"] = "3600"
response.headers["Cache-Control"] = "no-cache, no-store"
return response
2026-01-08 01:00:26 +10:30
@app.after_request
def after_request_cors(response):
"""Add CORS headers to non-preflight responses."""
2026-01-08 01:00:26 +10:30
origin = request.headers.get("Origin")
cors_origins = app.config.get("CORS_ORIGINS", [])
allow_origin = _cors_origin_header(cors_origins, origin)
if allow_origin:
response.headers["Access-Control-Allow-Origin"] = allow_origin
response.headers["Access-Control-Allow-Methods"] = ALLOWED_METHODS
response.headers["Access-Control-Allow-Headers"] = ALLOWED_HEADERS
if supports_credentials:
response.headers["Access-Control-Allow-Credentials"] = "true"
2026-01-08 01:00:26 +10:30
response.headers["Access-Control-Max-Age"] = "3600"
return response