You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

85 lines
3.0 KiB
Python

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)