Update main.py
Browse files
main.py
CHANGED
|
@@ -15,7 +15,6 @@ async def lifespan(app: FastAPI):
|
|
| 15 |
"""
|
| 16 |
Manages the lifecycle of the HTTPX client.
|
| 17 |
The client is created on startup and gracefully closed on shutdown.
|
| 18 |
-
|
| 19 |
WARNING: This client has no timeout and no explicit connection pool limits.
|
| 20 |
"""
|
| 21 |
# timeout=None disables all client-side timeouts.
|
|
@@ -30,8 +29,8 @@ app = FastAPI(docs_url=None, redoc_url=None, lifespan=lifespan)
|
|
| 30 |
# --- Reverse Proxy Logic ---
|
| 31 |
async def _reverse_proxy(request: Request):
|
| 32 |
"""
|
| 33 |
-
Forwards a request specifically for the /
|
| 34 |
-
It injects required headers and
|
| 35 |
"""
|
| 36 |
client: httpx.AsyncClient = request.app.state.http_client
|
| 37 |
|
|
@@ -42,13 +41,14 @@ async def _reverse_proxy(request: Request):
|
|
| 42 |
# Start with headers from the incoming request.
|
| 43 |
request_headers = dict(request.headers)
|
| 44 |
|
| 45 |
-
# 1. CRITICAL: Remove host
|
| 46 |
# The 'host' header is managed by httpx.
|
| 47 |
-
# Removing 'authorization' prevents the user's key from reaching the backend.
|
| 48 |
request_headers.pop("host", None)
|
| 49 |
-
request_headers.pop("authorization", None)
|
| 50 |
|
| 51 |
-
# 2.
|
|
|
|
|
|
|
|
|
|
| 52 |
# This will overwrite any conflicting headers from the original request.
|
| 53 |
specific_headers = {
|
| 54 |
"accept": "application/json, text/plain, */*",
|
|
@@ -67,6 +67,10 @@ async def _reverse_proxy(request: Request):
|
|
| 67 |
}
|
| 68 |
request_headers.update(specific_headers)
|
| 69 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 70 |
# Build the final request to the target service.
|
| 71 |
rp_req = client.build_request(
|
| 72 |
method=request.method,
|
|
@@ -108,4 +112,4 @@ async def health_check():
|
|
| 108 |
"""Provides a basic health check endpoint."""
|
| 109 |
return {"status": "ok", "proxying_endpoint": "/completions", "target": "TypeGPT"}
|
| 110 |
|
| 111 |
-
# Any request to a path other than "/
|
|
|
|
| 15 |
"""
|
| 16 |
Manages the lifecycle of the HTTPX client.
|
| 17 |
The client is created on startup and gracefully closed on shutdown.
|
|
|
|
| 18 |
WARNING: This client has no timeout and no explicit connection pool limits.
|
| 19 |
"""
|
| 20 |
# timeout=None disables all client-side timeouts.
|
|
|
|
| 29 |
# --- Reverse Proxy Logic ---
|
| 30 |
async def _reverse_proxy(request: Request):
|
| 31 |
"""
|
| 32 |
+
Forwards a request specifically for the /completions endpoint to the target URL.
|
| 33 |
+
It injects required headers and allows for a user-provided Authorization header.
|
| 34 |
"""
|
| 35 |
client: httpx.AsyncClient = request.app.state.http_client
|
| 36 |
|
|
|
|
| 41 |
# Start with headers from the incoming request.
|
| 42 |
request_headers = dict(request.headers)
|
| 43 |
|
| 44 |
+
# 1. CRITICAL: Remove host header.
|
| 45 |
# The 'host' header is managed by httpx.
|
|
|
|
| 46 |
request_headers.pop("host", None)
|
|
|
|
| 47 |
|
| 48 |
+
# 2. Get the user's authorization key from the incoming request.
|
| 49 |
+
authorization_header = request.headers.get("authorization")
|
| 50 |
+
|
| 51 |
+
# 3. Set the specific, required headers for the target API.
|
| 52 |
# This will overwrite any conflicting headers from the original request.
|
| 53 |
specific_headers = {
|
| 54 |
"accept": "application/json, text/plain, */*",
|
|
|
|
| 67 |
}
|
| 68 |
request_headers.update(specific_headers)
|
| 69 |
|
| 70 |
+
# 4. Add the user's authorization key to the headers if it exists.
|
| 71 |
+
if authorization_header:
|
| 72 |
+
request_headers["authorization"] = authorization_header
|
| 73 |
+
|
| 74 |
# Build the final request to the target service.
|
| 75 |
rp_req = client.build_request(
|
| 76 |
method=request.method,
|
|
|
|
| 112 |
"""Provides a basic health check endpoint."""
|
| 113 |
return {"status": "ok", "proxying_endpoint": "/completions", "target": "TypeGPT"}
|
| 114 |
|
| 115 |
+
# Any request to a path other than "/completions" or "/" will result in a 404 Not Found.
|