from fastapi import FastAPI, HTTPException, Request from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import JSONResponse import httpx import os import sys import socketio from pathlib import Path # Add shared modules to path sys.path.append(str(Path(__file__).parent.parent.parent.parent / "shared")) from websocket.socket_manager import socket_manager app = FastAPI( title="Know Foolery API Gateway", description="API Gateway for Know Foolery quiz game", version="1.0.0" ) # Create Socket.IO ASGI app socket_app = socketio.ASGIApp(socket_manager.sio, app) app.add_middleware( CORSMiddleware, allow_origins=["http://localhost:3000", "http://localhost:5173"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) SERVICES = { "game": os.getenv("GAME_SERVICE_URL", "http://game-service:8001"), "question": os.getenv("QUESTION_SERVICE_URL", "http://question-service:8002"), "player": os.getenv("PLAYER_SERVICE_URL", "http://player-service:8003"), "admin": os.getenv("ADMIN_SERVICE_URL", "http://admin-service:8004"), } async def forward_request(service: str, path: str, method: str, **kwargs): if service not in SERVICES: raise HTTPException(status_code=404, detail="Service not found") service_url = f"{SERVICES[service]}{path}" async with httpx.AsyncClient() as client: response = await client.request(method, service_url, **kwargs) return JSONResponse( content=response.json() if response.headers.get("content-type", "").startswith("application/json") else response.text, status_code=response.status_code ) @app.get("/health") async def health_check(): return {"status": "healthy", "service": "api-gateway"} @app.api_route("/api/game/{path:path}", methods=["GET", "POST", "PUT", "DELETE"]) async def game_proxy(path: str, request: Request): body = await request.body() return await forward_request("game", f"/{path}", request.method, content=body, headers=dict(request.headers)) @app.api_route("/api/questions/{path:path}", methods=["GET", "POST", "PUT", "DELETE"]) async def question_proxy(path: str, request: Request): body = await request.body() return await forward_request("question", f"/{path}", request.method, content=body, headers=dict(request.headers)) @app.api_route("/api/players/{path:path}", methods=["GET", "POST", "PUT", "DELETE"]) async def player_proxy(path: str, request: Request): body = await request.body() return await forward_request("player", f"/{path}", request.method, content=body, headers=dict(request.headers)) @app.api_route("/api/admin/{path:path}", methods=["GET", "POST", "PUT", "DELETE"]) async def admin_proxy(path: str, request: Request): body = await request.body() return await forward_request("admin", f"/{path}", request.method, content=body, headers=dict(request.headers)) if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=8000)