| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879 |
- import logging
- from typing import List
- import httpx
- from fastapi import FastAPI, Request, Response, HTTPException
- from starlette.status import HTTP_502_BAD_GATEWAY
- from alien_gateway.config import settings
- app = FastAPI(
- title=f"{settings.PROJECT_NAME} - Gateway & Auth Service",
- version="1.0.0"
- )
- logger = logging.getLogger("alien_gateway")
- @app.get("/health")
- async def health():
- return {"service": "alien_gateway", "status": "ok"}
- # 此模块未来将承担 JWT 签发、权限校验中间件、路由聚合等核心功能
- @app.post("/auth/login")
- async def login():
- return {"message": "Auth logic here"}
- HOP_BY_HOP_HEADERS: List[str] = [
- "connection",
- "keep-alive",
- "proxy-authenticate",
- "proxy-authorization",
- "te",
- "trailers",
- "transfer-encoding",
- "upgrade",
- ]
- def _clean_headers(headers):
- """移除 hop-by-hop 头,避免转发问题。"""
- return {k: v for k, v in headers.items() if k.lower() not in HOP_BY_HOP_HEADERS}
- @app.api_route("/api/store/{full_path:path}", methods=["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"])
- async def proxy_to_store(full_path: str, request: Request):
- """
- 简易网关:监听 33333 端口,将 /api/store/* 转发到 alien_store 服务。
- """
- target_url = f"{settings.STORE_BASE_URL}/api/store/{full_path}"
- client_ip = request.client.host if request.client else "-"
- # 读取请求体
- body = await request.body()
- # 过滤头部
- headers = _clean_headers(dict(request.headers))
- try:
- async with httpx.AsyncClient(timeout=30.0) as client:
- resp = await client.request(
- request.method,
- target_url,
- content=body,
- headers=headers,
- params=request.query_params,
- )
- except Exception as exc:
- logger.error("proxy to store failed ip=%s url=%s err=%s", client_ip, target_url, exc)
- raise HTTPException(status_code=HTTP_502_BAD_GATEWAY, detail="Upstream unavailable")
- # 返回下游响应
- return Response(
- content=resp.content,
- status_code=resp.status_code,
- headers=_clean_headers(resp.headers),
- media_type=resp.headers.get("content-type"),
- )
- if __name__ == "__main__":
- import uvicorn
- uvicorn.run(app, host="0.0.0.0", port=33333)
|