Spaces:
Sleeping
Sleeping
File size: 3,314 Bytes
03c899c 6ea66c7 9a65bf8 9940432 f4cda89 9940432 9e23a59 4f151a3 8a272dd 8d2b37c 8a272dd ebfb44a 8a272dd 9940432 6ea66c7 9940432 f4cda89 6ea66c7 f4cda89 8a272dd 9940432 9a65bf8 f4cda89 8a272dd f4cda89 8a272dd f4cda89 9a65bf8 6ea66c7 9940432 845a5a8 9940432 f4cda89 9940432 845a5a8 9940432 |
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://api.openai.com/v1"
CLIENT_TIMEOUT = 400.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) |