Spaces:
Paused
Paused
File size: 3,314 Bytes
03c899c c6769df 5c4cc48 f4cda89 5c4cc48 36c9cd4 5c4cc48 f4cda89 5c4cc48 c6769df f4cda89 5c4cc48 c6769df 5c4cc48 f4cda89 c6769df f4cda89 c6769df 5c4cc48 c6769df f4cda89 c6769df f4cda89 c6769df f4cda89 c6769df 5c4cc48 f4cda89 5c4cc48 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
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) |