Rooni's picture
Update app.py
5c4cc48 verified
raw
history blame
3.31 kB
import os
import httpx
from fastapi import FastAPI, Request, Response
from contextlib import asynccontextmanager
# --- КОНФИГУРАЦИЯ ---
OR_BASE_URL = "https://openrouter.ai/api"
CLIENT_TIMEOUT = 280.0
# "Hop-by-hop" заголовки, которые не должны проксироваться
HOP_BY_HOP_HEADERS = {
"connection", "keep-alive", "proxy-authenticate", "proxy-authorization",
"te", "trailers", "transfer-encoding", "upgrade",
}
# --- УПРАВЛЕНИЕ ЖИЗНЕННЫМ ЦИКЛОМ КЛИЕНТА ---
# Это самый надежный способ управлять httpx.AsyncClient в FastAPI
@asynccontextmanager
async def lifespan(app: FastAPI):
# Код, который выполняется при старте сервера
async with httpx.AsyncClient(base_url=OR_BASE_URL, timeout=CLIENT_TIMEOUT) as client:
print("INFO: HTTPX Client started.")
# Передаем созданный клиент в состояние приложения
app.state.http_client = client
yield
# Код, который выполняется при остановке сервера (клиент закрывается автоматически)
print("INFO: HTTPX Client closed.")
# --- ПРИЛОЖЕНИЕ FASTAPI ---
app = FastAPI(
title="Robust OpenAI Proxy",
description="A non-streaming proxy with proper client lifecycle management.",
lifespan=lifespan # Подключаем наш менеджер жизненного цикла
)
# --- ЭНДПОИНТЫ ---
@app.get("/")
async def home():
return {"status": "ok", "message": "Robust, non-streaming OpenAI proxy is working."}
@app.api_route("/{endpoint:path}", methods=["GET", "POST", "PUT", "PATCH", "DELETE"])
async def proxy(endpoint: str, request: Request):
try:
url = httpx.URL(path=f"/{endpoint}", query=request.url.query.encode("utf-8"))
headers = {k: v for k, v in request.headers.items() if k.lower() != "host"}
body = await request.body()
# Получаем клиент из состояния приложения, а не из глобальной переменной
client: httpx.AsyncClient = request.app.state.http_client
resp_openai = await client.request(
method=request.method,
url=url,
headers=headers,
content=body
)
response_headers = {
k: v for k, v in resp_openai.headers.items()
if k.lower() not in HOP_BY_HOP_HEADERS
}
return Response(
content=resp_openai.content,
status_code=resp_openai.status_code,
headers=response_headers
)
except httpx.RequestError as e:
# Эта ошибка все еще возможна, если OpenAI недоступен
print(f"!!! HTTPX Request Error Caught: {e!r}")
return Response(content=f"Could not connect to OpenAI API. Details: {e!r}", status_code=502)
except Exception as e:
# Эта ошибка ловит все остальное, что и вызывало 500
print(f"!!! Generic Error Caught: {e!r}")
return Response(content=f"An internal proxy error occurred. Details: {e!r}", status_code=500)