frankie567 / httpx-ws

WebSocket support for HTTPX
https://frankie567.github.io/httpx-ws/
MIT License
110 stars 17 forks source link

aconnect_ws does not work with AsyncClient bound to an app #66

Closed pavelschon closed 8 months ago

pavelschon commented 8 months ago

Describe the bug

aconnect_ws does not work with an app which is bound to an existing FastAPI app.

To Reproduce

@pytest.fixture(name="client")
async def fixture_client(api: FastAPI) -> AsyncIterator[AsyncClient]:
    async with AsyncClient(app=api, base_url="http://test") as client:
        yield client

async def test_websocket(client: AsyncClient) -> None:
    async with aconnect_ws("/ws/", client) as ws:
        data = await ws.receive_json()

I get:

    @contextlib.asynccontextmanager
    async def _aconnect_ws(
        url: str,
        client: httpx.AsyncClient,
        *,
        max_message_size_bytes: int = DEFAULT_MAX_MESSAGE_SIZE_BYTES,
        queue_size: int = DEFAULT_QUEUE_SIZE,
        keepalive_ping_interval_seconds: typing.Optional[
            float
        ] = DEFAULT_KEEPALIVE_PING_INTERVAL_SECONDS,
        keepalive_ping_timeout_seconds: typing.Optional[
            float
        ] = DEFAULT_KEEPALIVE_PING_TIMEOUT_SECONDS,
        subprotocols: typing.Optional[typing.List[str]] = None,
        **kwargs: typing.Any,
    ) -> typing.AsyncGenerator[AsyncWebSocketSession, None]:
        headers = kwargs.pop("headers", {})
        headers.update(_get_headers(subprotocols))

        async with client.stream("GET", url, headers=headers, **kwargs) as response:
            if response.status_code != 101:
>               raise WebSocketUpgradeError(response)
E               httpx_ws._exceptions.WebSocketUpgradeError: <Response [404 Not Found]>

Obviously, the endpoint /ws/ exists within the app.

Expected behavior

It should call directly the FastAPI app, no TCP/HTTP connection should be made.

Configuration

frankie567 commented 8 months ago

That's explained in the docs. You can't use the app= parameter (side note: it'll also be deprecated in HTTPX); you need to pass a specific transport: https://frankie567.github.io/httpx-ws/usage/asgi/