diff --git a/app/main.py b/app/main.py index 06dc331..ea5cade 100644 --- a/app/main.py +++ b/app/main.py @@ -43,10 +43,10 @@ async def lifespan(app: FastAPI): # 1. Initialize Logging early but safely setup_logging(config.settings) log.info('### **** *** ** * Aether API v4 using FastAPI - Startup Lifespan Initiated * ** *** **** ###') - + # 2. Bootstrapping Configuration from DB with robust error handling log.info("Bootstrapping Configuration...") - + # Save original settings for fallback orig_db_server = config.settings.DB_SERVER orig_db_user = config.settings.DB_USER @@ -81,11 +81,11 @@ async def lifespan(app: FastAPI): # 3. Final validation of critical infrastructure validate_critical_config(config.settings) - + log.info('### **** *** ** * Aether API v4 using FastAPI - Startup Sequence Complete * ** *** **** ###') - + yield - + # Shutdown logic log.info('### **** *** ** * Aether API v4 using FastAPI - Shutdown Lifespan Initiated * ** *** **** ###') log.info('The Aether FastAPI API is shutting down...') @@ -114,6 +114,7 @@ app.mount('/static', StaticFiles(directory='static'), name='static') setup_routers(app) +# Updated 2026-02-23 # BEGIN: CORS # NOTE: Eventually this should query the DB for the specific list based on the cfg table and or site_domain table. That way it is dynamic and only allowing those defined in the DB. No wildcards or regex. # NOTE: Need to include .localhost for less browser restrictions! Mainly for audio and video. @@ -132,6 +133,44 @@ app.add_middleware( # END: CORS +# Updated 2026-02-23 +# Add middleware to ensure Access-Control-Allow-Private-Network is present +# when the response already includes CORS allow-origin (i.e. origin was allowed). +@app.middleware("http") +async def cors_pna_middleware(request: Request, call_next): + """Add `Access-Control-Allow-Private-Network: true` to responses + only when CORS has already allowed the request's origin. This avoids + echoing PNA for disallowed origins and leverages the existing + CORSMiddleware origin validation. + """ + response = await call_next(request) + # Rely on existing CORS logic (CORSMiddleware) to validate origin. + # Only add the PNA header if an Allow-Origin header is present. + if response.headers.get('access-control-allow-origin') or response.headers.get('Access-Control-Allow-Origin'): + response.headers['Access-Control-Allow-Private-Network'] = 'true' + return response + + +# Updated 2026-02-23 +# Temporary debug middleware: logs Origin and PNA-related request/response headers +# Activate only when an Origin header is present to limit log noise. +# @app.middleware("http") +# async def debug_pna_logging_middleware(request: Request, call_next): +# origin = request.headers.get('origin') +# if origin: +# acrpn = request.headers.get('access-control-request-private-network') +# acrm = request.headers.get('access-control-request-method') +# log.debug(f"PNA_DEBUG REQ: method={request.method} path={request.url.path} remote={getattr(request.client, 'host', None)} origin={origin} acr_method={acrm} acr_private_network={acrpn}") + +# response = await call_next(request) + +# if origin: +# # collect CORS/PNA-related response headers for visibility +# interesting = {k: v for k, v in response.headers.items() if k.lower().startswith('access-control-') or k.lower() == 'vary'} +# log.debug(f"PNA_DEBUG RESP: status={response.status_code} headers={interesting}") + +# return response + # Register utility middleware from external module app.middleware('http')(process_time_middleware)