Step 2: Add Users microservice with API Gateway routing

- Created Users service with full CRUD operations
- Updated Console to act as API Gateway for Users service
- Implemented service-to-service communication
- Added service health monitoring in Console
- Docker Compose now manages both services

Services running:
- Console (API Gateway): http://localhost:8011
- Users service: Internal network only

Test endpoints:
- Status: curl http://localhost:8011/api/status
- Users: curl http://localhost:8011/api/users/users

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
jungwoo choi
2025-09-10 16:09:36 +09:00
parent 52b76d0e77
commit 7559c4c5a8
6 changed files with 237 additions and 11 deletions

View File

@ -1,7 +1,10 @@
from fastapi import FastAPI
from fastapi import FastAPI, HTTPException, Request, Response
from fastapi.middleware.cors import CORSMiddleware
import uvicorn
from datetime import datetime
import httpx
import os
from typing import Any
app = FastAPI(
title="Console API Gateway",
@ -9,6 +12,9 @@ app = FastAPI(
version="0.1.0"
)
# Service URLs from environment
USERS_SERVICE_URL = os.getenv("USERS_SERVICE_URL", "http://users-backend:8000")
# CORS middleware
app.add_middleware(
CORSMiddleware,
@ -36,19 +42,66 @@ async def health_check():
@app.get("/api/status")
async def system_status():
services_status = {}
# Check Users service
try:
async with httpx.AsyncClient() as client:
response = await client.get(f"{USERS_SERVICE_URL}/health", timeout=2.0)
services_status["users"] = "online" if response.status_code == 200 else "error"
except:
services_status["users"] = "offline"
# Other services (not yet implemented)
services_status["oauth"] = "pending"
services_status["images"] = "pending"
services_status["applications"] = "pending"
services_status["data"] = "pending"
services_status["statistics"] = "pending"
return {
"console": "online",
"services": {
"users": "pending",
"oauth": "pending",
"images": "pending",
"applications": "pending",
"data": "pending",
"statistics": "pending"
},
"services": services_status,
"timestamp": datetime.now().isoformat()
}
# API Gateway - Route to Users service
@app.api_route("/api/users/{path:path}", methods=["GET", "POST", "PUT", "DELETE", "PATCH"])
async def proxy_to_users(path: str, request: Request):
"""Proxy requests to Users service"""
try:
async with httpx.AsyncClient() as client:
# Build the target URL
url = f"{USERS_SERVICE_URL}/{path}"
# Get request body if exists
body = None
if request.method in ["POST", "PUT", "PATCH"]:
body = await request.body()
# Forward the request
response = await client.request(
method=request.method,
url=url,
headers={
key: value for key, value in request.headers.items()
if key.lower() not in ["host", "content-length"]
},
content=body,
params=request.query_params
)
# Return the response
return Response(
content=response.content,
status_code=response.status_code,
headers=dict(response.headers)
)
except httpx.ConnectError:
raise HTTPException(status_code=503, detail="Users service unavailable")
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
if __name__ == "__main__":
uvicorn.run(
"main:app",