Merge from Dev to LOAF Production #23
111
server.py
111
server.py
@@ -808,6 +808,53 @@ async def get_config():
|
|||||||
"max_file_size_mb": int(max_file_size_mb)
|
"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
|
# User Profile Routes
|
||||||
@api_router.get("/users/profile", response_model=UserResponse)
|
@api_router.get("/users/profile", response_model=UserResponse)
|
||||||
async def get_profile(current_user: User = Depends(get_current_user)):
|
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
|
# Include the router in the main app
|
||||||
app.include_router(api_router)
|
app.include_router(api_router)
|
||||||
|
|
||||||
# CORS Configuration
|
# ============================================================================
|
||||||
cors_origins = os.environ.get('CORS_ORIGINS', '')
|
# MIDDLEWARE CONFIGURATION
|
||||||
if cors_origins:
|
# ============================================================================
|
||||||
# Use explicitly configured origins
|
# IMPORTANT: In FastAPI, middleware is executed in REVERSE order of addition
|
||||||
allowed_origins = [origin.strip() for origin in cors_origins.split(',')]
|
# Last added = First executed
|
||||||
else:
|
# So we add them in this order: Security Headers -> CORS
|
||||||
# Default to common development origins if not configured
|
# Execution order will be: CORS -> Security Headers
|
||||||
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}")
|
# Security Headers Middleware (Added first, executes second)
|
||||||
|
|
||||||
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
|
|
||||||
@app.middleware("http")
|
@app.middleware("http")
|
||||||
async def add_security_headers(request: Request, call_next):
|
async def add_security_headers(request: Request, call_next):
|
||||||
response = await call_next(request)
|
response = await call_next(request)
|
||||||
@@ -6319,3 +6346,31 @@ async def add_security_headers(request: Request, call_next):
|
|||||||
return response
|
return response
|
||||||
|
|
||||||
print(f"✓ Security headers configured (Production: {IS_PRODUCTION})")
|
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
|
||||||
|
)
|
||||||
Reference in New Issue
Block a user