Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Decoding of streaming response fails if the response contains headers with colons. #324

Open
natuspati opened this issue Jan 14, 2025 · 0 comments

Comments

@natuspati
Copy link

Description of the Issue

When decoding a streaming response, the presence of colons (:) in the headers causes the process to fail. This results in an error, making it impossible to handle certain responses with specific header formats.

Steps to Reproduce

Use the following code to simulate a streaming response with colons in the headers:

import uvicorn
from cashews import cache
from fastapi import FastAPI
from starlette.responses import StreamingResponse


app = FastAPI()
cache.setup("mem://?size=500")

_DATA = "data," * 10


async def _stream_data():
    print("Fetching data...")
    for data in _DATA.split():
        yield data


@app.get("/stream")
@cache(ttl="1m")
async def stream():
    headers = {"Date": "Tue, 14 Jan 2025 14:33:02 GMT", "Max-Forwards": "10"}
    return StreamingResponse(
        content=_stream_data(),
        headers=headers,
    )


if __name__ == "__main__":
    uvicorn.run(app, host="localhost")

The headers in the response contain colons, which triggers the error.

Expected Behavior

The streaming response is cached on the first request. On the following requests, the response is retrieved from cache and decoded correctly, even if colons are present in the headers.

Actual Behavior

The response is saved to the cache, but the decoding process fails, resulting in the following error:

server_error
server_error_2

Environment

Python Version: 3.10
Framework Version: fastapi 0.115.5 

Proposed Solution

When decoding the raw value and splitting status_code from headers, use only a single split.

cashews/contrib/_starlette.py

async def decode_streaming_response(value: bytes, backend: Backend, key: str, **kwargs) -> StreamingResponse:
    if not await backend.get(f"{key}:done"):
        raise DecodeError()
    status_code, headers = value.split(b":", maxsplit=1)
    ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant