diff --git a/backend/open_webui/routers/ollama.py b/backend/open_webui/routers/ollama.py index b957310b5..8311fee5d 100644 --- a/backend/open_webui/routers/ollama.py +++ b/backend/open_webui/routers/ollama.py @@ -86,6 +86,17 @@ log = logging.getLogger(__name__) # ########################################## +# Headers that become stale after aiohttp auto-decompresses the upstream +# response body. Forwarding them verbatim causes desktop / programmatic +# clients to attempt decompression of an already-decoded payload, resulting +# in ZlibError. See https://github.com/aio-libs/aiohttp/issues/4462. +_STRIP_PROXY_HEADERS = frozenset({'Content-Encoding', 'Content-Length', 'Transfer-Encoding'}) + + +def _clean_proxy_headers(raw_headers) -> dict: + """Return a copy of *raw_headers* with stale encoding headers removed.""" + return {k: v for k, v in raw_headers.items() if k not in _STRIP_PROXY_HEADERS} + async def send_get_request(url, key=None, user: UserModel = None): timeout = aiohttp.ClientTimeout(total=AIOHTTP_CLIENT_TIMEOUT_MODEL_LIST) @@ -163,7 +174,7 @@ async def send_request( r.raise_for_status() if stream: - response_headers = dict(r.headers) + response_headers = _clean_proxy_headers(r.headers) if content_type: response_headers['Content-Type'] = content_type diff --git a/backend/open_webui/routers/openai.py b/backend/open_webui/routers/openai.py index 8a7c3aca7..6f8c0f81b 100644 --- a/backend/open_webui/routers/openai.py +++ b/backend/open_webui/routers/openai.py @@ -76,6 +76,17 @@ log = logging.getLogger(__name__) # ########################################## +# Headers that become stale after aiohttp auto-decompresses the upstream +# response body. Forwarding them verbatim causes desktop / programmatic +# clients to attempt decompression of an already-decoded payload, resulting +# in ZlibError. See https://github.com/aio-libs/aiohttp/issues/4462. +_STRIP_PROXY_HEADERS = frozenset({'Content-Encoding', 'Content-Length', 'Transfer-Encoding'}) + + +def _clean_proxy_headers(raw_headers) -> dict: + """Return a copy of *raw_headers* with stale encoding headers removed.""" + return {k: v for k, v in raw_headers.items() if k not in _STRIP_PROXY_HEADERS} + async def send_get_request( request: Request = None, @@ -1219,7 +1230,7 @@ async def generate_chat_completion( return StreamingResponse( stream_wrapper(r, content_handler=stream_chunks_handler), status_code=r.status, - headers=dict(r.headers), + headers=_clean_proxy_headers(r.headers), ) else: try: @@ -1304,7 +1315,7 @@ async def embeddings(request: Request, form_data: dict, user): return StreamingResponse( stream_wrapper(r), status_code=r.status, - headers=dict(r.headers), + headers=_clean_proxy_headers(r.headers), ) else: try: @@ -1425,7 +1436,7 @@ async def responses( return StreamingResponse( stream_wrapper(r), status_code=r.status, - headers=dict(r.headers), + headers=_clean_proxy_headers(r.headers), ) else: try: @@ -1542,7 +1553,7 @@ async def proxy(path: str, request: Request, user=Depends(get_verified_user)): return StreamingResponse( stream_wrapper(r), status_code=r.status, - headers=dict(r.headers), + headers=_clean_proxy_headers(r.headers), ) else: try: