@@ -61,12 +61,9 @@ async def get_openai_client(api_key: str, request: Request) -> AsyncOpenAI:
6161
6262
6363async def check_httpx_err (body : str | bytes , api_key : str | None ):
64- # too big for error
65- if len (body ) > 4000 or not api_key :
64+ # too big or small for error
65+ if 10 > len (body ) > 4000 or not api_key :
6666 return
67- if (isinstance (body , str ) and body .startswith ("data: " ) or (
68- isinstance (body , bytes ) and body .startswith (b"data: " ))):
69- body = body [6 :]
7067 has_rate_limit_error , reset_time_ms = await check_rate_limit (body )
7168 if has_rate_limit_error :
7269 await key_manager .disable_key (api_key , reset_time_ms )
@@ -287,30 +284,28 @@ async def proxy_with_httpx(
287284 """Fall back to httpx for endpoints not supported by the OpenAI SDK."""
288285 free_only = (any (f"/api/v1{ path } " == ep for ep in MODELS_ENDPOINTS ) and
289286 config ["openrouter" ]["free_only" ])
290- headers = prepare_forward_headers (request )
291287 req_kwargs = {
292288 "method" : request .method ,
293289 "url" : f"{ config ['openrouter' ]['base_url' ]} { path } " ,
294- "headers" : headers ,
290+ "headers" : prepare_forward_headers ( request ) ,
295291 "content" : await request .body (),
292+ "params" : request .query_params ,
296293 }
297- # Add query parameters if they exist
298- if request .query_params :
299- req_kwargs ["url" ] = f"{ req_kwargs ['url' ]} ?{ request .url .query } "
300-
301294 if api_key :
302295 req_kwargs ["headers" ]["Authorization" ] = f"Bearer { api_key } "
303296
304297 client = await get_async_client (request )
305298 try :
306- openrouter_resp = await client .request (** req_kwargs )
299+ openrouter_req = client .build_request (** req_kwargs )
300+ openrouter_resp = await client .send (openrouter_req , stream = is_stream )
301+
307302 headers = dict (openrouter_resp .headers )
308303 # Content has already been decoded
309304 headers .pop ("content-encoding" , None )
310305 headers .pop ("Content-Encoding" , None )
311306
312307 if not is_stream :
313- body = await openrouter_resp .aread ()
308+ body = openrouter_resp .content
314309 await check_httpx_err (body , api_key )
315310 if free_only :
316311 body = remove_paid_models (body )
@@ -319,30 +314,26 @@ async def proxy_with_httpx(
319314 status_code = openrouter_resp .status_code ,
320315 headers = headers ,
321316 )
322- if not api_key and not is_completion :
323- return StreamingResponse (
324- openrouter_resp .aiter_bytes (),
325- status_code = openrouter_resp .status_code ,
326- headers = headers ,
327- )
328317
329318 async def stream_completion ():
330- data = ''
319+ if not (api_key or is_completion ):
320+ try :
321+ async for chunk in openrouter_resp .aiter_bytes ():
322+ yield chunk
323+ finally :
324+ await openrouter_resp .aclose ()
325+ return
326+ last_json = ""
331327 try :
332328 async for line in openrouter_resp .aiter_lines ():
333- if line .startswith ("data: " ):
334- data = line [6 :] # Get data without 'data: ' prefix
335- if data == "[DONE]" :
336- yield "data: [DONE]\n \n " .encode ("utf-8" )
337- else :
338- # Forward the original data without reformatting
339- data = line
340- yield f"{ line } \n \n " .encode ("utf-8" )
341- elif line :
342- yield f"{ line } \n \n " .encode ("utf-8" )
329+ if line .startswith ("data: {" ): # get json only
330+ last_json = line [6 :]
331+ yield f"{ line } \n \n " .encode ("utf-8" )
343332 except Exception as err :
344333 logger .error ("stream_completion error: %s" , err )
345- await check_httpx_err (data , api_key )
334+ finally :
335+ await openrouter_resp .aclose ()
336+ await check_httpx_err (last_json , api_key )
346337
347338
348339 return StreamingResponse (
0 commit comments