diff --git a/server.py b/server.py index 506f7e9..561d540 100644 --- a/server.py +++ b/server.py @@ -808,6 +808,53 @@ async def get_config(): "max_file_size_mb": int(max_file_size_mb) } +@api_router.get("/diagnostics/cors") +async def cors_diagnostics(request: Request): + """ + CORS Diagnostics Endpoint + Shows current CORS configuration and request details for debugging + + Use this to verify: + 1. What origins are allowed + 2. What origin is making the request + 3. Whether CORS is properly configured + """ + cors_origins_env = os.environ.get('CORS_ORIGINS', '') + + if cors_origins_env: + configured_origins = [origin.strip() for origin in cors_origins_env.split(',')] + cors_status = "✅ CONFIGURED" + else: + configured_origins = [ + "http://localhost:3000", + "http://localhost:8000", + "http://127.0.0.1:3000", + "http://127.0.0.1:8000" + ] + cors_status = "⚠️ NOT CONFIGURED (using defaults)" + + request_origin = request.headers.get('origin', 'None') + origin_allowed = request_origin in configured_origins + + return { + "cors_status": cors_status, + "environment": ENVIRONMENT, + "cors_origins_env_variable": cors_origins_env or "(not set)", + "allowed_origins": configured_origins, + "request_origin": request_origin, + "origin_allowed": origin_allowed, + "diagnosis": { + "cors_configured": bool(cors_origins_env), + "origin_matches": origin_allowed, + "issue": None if origin_allowed else f"Origin '{request_origin}' is not in allowed origins list" + }, + "fix_instructions": None if origin_allowed else ( + f"Add to backend .env file:\n" + f"CORS_ORIGINS={request_origin}" + f"{(',' + ','.join(configured_origins)) if cors_origins_env else ''}" + ) + } + # User Profile Routes @api_router.get("/users/profile", response_model=UserResponse) async def get_profile(current_user: User = Depends(get_current_user)): @@ -6254,35 +6301,15 @@ async def stripe_webhook(request: Request, db: Session = Depends(get_db)): # Include the router in the main app app.include_router(api_router) -# CORS Configuration -cors_origins = os.environ.get('CORS_ORIGINS', '') -if cors_origins: - # Use explicitly configured origins - allowed_origins = [origin.strip() for origin in cors_origins.split(',')] -else: - # Default to common development origins if not configured - allowed_origins = [ - "http://localhost:3000", - "http://localhost:8000", - "http://127.0.0.1:3000", - "http://127.0.0.1:8000" - ] - print(f"⚠️ WARNING: CORS_ORIGINS not set. Using defaults: {allowed_origins}") - print("⚠️ For production, set CORS_ORIGINS in .env file!") +# ============================================================================ +# MIDDLEWARE CONFIGURATION +# ============================================================================ +# IMPORTANT: In FastAPI, middleware is executed in REVERSE order of addition +# Last added = First executed +# So we add them in this order: Security Headers -> CORS +# Execution order will be: CORS -> Security Headers -print(f"✓ CORS allowed origins: {allowed_origins}") - -app.add_middleware( - CORSMiddleware, - allow_credentials=True, - allow_origins=allowed_origins, - allow_methods=["GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH"], - allow_headers=["*"], - expose_headers=["*"], - max_age=600, # Cache preflight requests for 10 minutes -) - -# Security Headers Middleware +# Security Headers Middleware (Added first, executes second) @app.middleware("http") async def add_security_headers(request: Request, call_next): response = await call_next(request) @@ -6318,4 +6345,32 @@ async def add_security_headers(request: Request, call_next): return response -print(f"✓ Security headers configured (Production: {IS_PRODUCTION})") \ No newline at end of file +print(f"✓ Security headers configured (Production: {IS_PRODUCTION})") + +# CORS Configuration (Added second, executes first) +cors_origins = os.environ.get('CORS_ORIGINS', '') +if cors_origins: + # Use explicitly configured origins + allowed_origins = [origin.strip() for origin in cors_origins.split(',')] +else: + # Default to common development origins if not configured + allowed_origins = [ + "http://localhost:3000", + "http://localhost:8000", + "http://127.0.0.1:3000", + "http://127.0.0.1:8000" + ] + print(f"⚠️ WARNING: CORS_ORIGINS not set. Using defaults: {allowed_origins}") + print("⚠️ For production, set CORS_ORIGINS in .env file!") + +print(f"✓ CORS allowed origins: {allowed_origins}") + +app.add_middleware( + CORSMiddleware, + allow_credentials=True, + allow_origins=allowed_origins, + allow_methods=["GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH"], + allow_headers=["*"], + expose_headers=["*"], + max_age=600, # Cache preflight requests for 10 minutes +) \ No newline at end of file