Skip to content

Cannot connect to FastAPI-based websocket server using the library while postman. #1624

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

Open
milk-bottle-liyu opened this issue Apr 27, 2025 · 5 comments
Labels

Comments

@milk-bottle-liyu
Copy link

I create a server using FastAPI and websockets, which looks like

from fastapi import FastAPI, WebSocket, WebSocketDisconnect
from fastapi.middleware.cors import CORSMiddleware
import asyncio 

app = FastAPI()

@app.websocket("/{group}/{player_name}")
async def websocket_endpoint(websocket: WebSocket, group, player_name):
    if group == 'human' and player_name == 'admin':
        if app.state.game_server.admin_sock is None:
            await websocket.accept()
        else:
            raise ValueError('admin connected')
        app.state.game_server.admin_sock = websocket
        logging.info(f'add admin')
    else:
        if player_name in app.state.game_server.game_config.player_list:
            raise ValueError(f'{player_name} conneccted')
        else:
            await websocket.accept()
        app.state.game_server.add_player(player_name, websocket)
        logging.info(f'add {player_name}')

    try:
        while True:
            data = await websocket.receive_text()
            logging.warning(f'from {player_name}: {data}')
            async with app.state.game_lock:
                await app.state.game_server.handle_msg(data, player_name)

            await asyncio.sleep(0.5)

    except WebSocketDisconnect:
        if group == 'human' and player_name == 'admin':
            app.state.game_server.admin_sock = None
        else:
            app.state.game_server.remove_player(player_name)
        logging.warning(f"player [{player_name}] disconnected")

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],

    allow_headers=["*", "Upgrade", "Connection"]
)

I try to connect the server using code below.

    import asyncio
    import signal

    from websockets.asyncio.client import connect as aconnect


    async def client():
        async with aconnect("ws://127.0.0.1:8000/agent/kimi") as websocket:
            # Close the connection when receiving SIGTERM.
            loop = asyncio.get_running_loop()
            loop.add_signal_handler(signal.SIGTERM, loop.create_task, websocket.close())

            # Process messages received on the connection.
            async for message in websocket:
                print(message)


    asyncio.run(client())

But it fails with outputs as follow.

Traceback (most recent call last):
  File "C:\Users\****\miniconda3\envs\wiu\lib\site-packages\websockets\http11.py", line 241, in parse
    status_line = yield from parse_line(read_line)
  File "C:\Users\****\miniconda3\envs\wiu\lib\site-packages\websockets\http11.py", line 309, in parse_line
    line = yield from read_line(MAX_LINE_LENGTH)
  File "C:\Users\****\miniconda3\envs\wiu\lib\site-packages\websockets\streams.py", line 46, in read_line
    raise EOFError(f"stream ends after {p} bytes, before end of line")
EOFError: stream ends after 0 bytes, before end of line

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "C:\Users\****\miniconda3\envs\wiu\lib\site-packages\websockets\client.py", line 301, in parse
    response = yield from Response.parse(
  File "C:\Users\****\miniconda3\envs\wiu\lib\site-packages\websockets\http11.py", line 243, in parse
    raise EOFError("connection closed while reading HTTP status line") from exc
EOFError: connection closed while reading HTTP status line

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "D:\code\****\BaseAgentPlayer.py", line 186, in <module>
    asyncio.run(client())
  File "C:\Users\****\miniconda3\envs\wiu\lib\asyncio\runners.py", line 44, in run
    return loop.run_until_complete(main)
  File "C:\Users\****\miniconda3\envs\wiu\lib\asyncio\base_events.py", line 649, in run_until_complete
    return future.result()
  File "D:\code\****\BaseAgentPlayer.py", line 176, in client
    async with aconnect("ws://127.0.0.1:8000/agent/kimi") as websocket:
  File "C:\Users\****\miniconda3\envs\wiu\lib\site-packages\websockets\asyncio\client.py", line 587, in __aenter__
    return await self
  File "C:\Users\****\miniconda3\envs\wiu\lib\site-packages\websockets\asyncio\client.py", line 543, in __await_impl__
    await self.connection.handshake(
  File "C:\Users\****\miniconda3\envs\wiu\lib\site-packages\websockets\asyncio\client.py", line 114, in handshake
    raise self.protocol.handshake_exc
websockets.exceptions.InvalidMessage: did not receive a valid HTTP response

I can connect to the server using postman and a client writen in vue, so I found it quite strange to me.

Please help with the issue~

@aaugustin
Copy link
Member

Can you enable debug logs (https://websockets.readthedocs.io/en/stable/howto/debugging.html) so we can see what happens on the wire?

@aaugustin
Copy link
Member

Ideally, do the same with Postman, so you can compare what postman sends with what websockets sends and figure out why your server accepts the former and not the latter.

@milk-bottle-liyu
Copy link
Author

Thanks for help!
The log of the fastapi server when connecting by postman is as follow.

INFO:     Started server process [17820]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
DEBUG:    = connection is CONNECTING
DEBUG:    < GET /agent/kimi HTTP/1.1
DEBUG:    < sec-websocket-version: 13
DEBUG:    < sec-websocket-key: ikoJKF3/r+AlwoaSyTxaYg==
DEBUG:    < connection: Upgrade
DEBUG:    < upgrade: websocket
DEBUG:    < sec-websocket-extensions: permessage-deflate; client_max_window_bits
DEBUG:    < host: 127.0.0.1:8000
INFO:     ('127.0.0.1', 59421) - "WebSocket /agent/kimi" [accepted]
DEBUG:    > HTTP/1.1 101 Switching Protocols
DEBUG:    > Upgrade: websocket
DEBUG:    > Connection: Upgrade
DEBUG:    > Sec-WebSocket-Accept: LFU0D2gegsyWqp5NGONXcgqDDSw=
DEBUG:    > Sec-WebSocket-Extensions: permessage-deflate
DEBUG:    > date: Tue, 29 Apr 2025 14:35:31 GMT
DEBUG:    > server: uvicorn
INFO:     connection open
DEBUG:    = connection is OPEN

When connecting using Python code, it seems that the server did not receive any data, as there is no output of log on the server side. The log of client is as follow.

2025-04-29 22:39:08,337 Using proactor: IocpProactor
2025-04-29 22:39:08,340 = connection is CONNECTING
2025-04-29 22:39:08,341 > GET /agent/kimi HTTP/1.1
2025-04-29 22:39:08,341 > Host: 127.0.0.1:8000
2025-04-29 22:39:08,341 > Upgrade: websocket
2025-04-29 22:39:08,341 > Connection: Upgrade
2025-04-29 22:39:08,341 > Sec-WebSocket-Key: lV6JnmW4N+Np6go3I7xL1Q==
2025-04-29 22:39:08,341 > Sec-WebSocket-Version: 13
2025-04-29 22:39:08,341 > Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
2025-04-29 22:39:08,342 > User-Agent: Python/3.10 websockets/15.0.1
2025-04-29 22:39:10,610 > EOF
2025-04-29 22:39:10,611 < EOF
2025-04-29 22:39:10,611 = connection is CLOSED
2025-04-29 22:39:10,612 x half-closing TCP connection
Traceback (most recent call last):
  File "C:\Users\ping\miniconda3\envs\wiu\lib\site-packages\websockets\http11.py", line 241, in parse
    status_line = yield from parse_line(read_line)
  File "C:\Users\ping\miniconda3\envs\wiu\lib\site-packages\websockets\http11.py", line 309, in parse_line
    line = yield from read_line(MAX_LINE_LENGTH)
  File "C:\Users\ping\miniconda3\envs\wiu\lib\site-packages\websockets\streams.py", line 46, in read_line
    raise EOFError(f"stream ends after {p} bytes, before end of line")
EOFError: stream ends after 0 bytes, before end of line

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "C:\Users\***\miniconda3\envs\wiu\lib\site-packages\websockets\client.py", line 301, in parse
    response = yield from Response.parse(
  File "C:\Users\***\miniconda3\envs\wiu\lib\site-packages\websockets\http11.py", line 243, in parse
    raise EOFError("connection closed while reading HTTP status line") from exc
EOFError: connection closed while reading HTTP status line

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "D:\code\who-is-undercover\test_demo.py", line 25, in <module>
    asyncio.run(client())
  File "C:\Users\***\miniconda3\envs\wiu\lib\asyncio\runners.py", line 44, in run
    return loop.run_until_complete(main)
  File "C:\Users\***\miniconda3\envs\wiu\lib\asyncio\base_events.py", line 649, in run_until_complete
    return future.result()
  File "D:\code\who-is-undercover\test_demo.py", line 15, in client
    async with aconnect("ws://127.0.0.1:8000/agent/kimi") as websocket:
  File "C:\Users\***\miniconda3\envs\wiu\lib\site-packages\websockets\asyncio\client.py", line 587, in __aenter__
    return await self
  File "C:\Users\***\miniconda3\envs\wiu\lib\site-packages\websockets\asyncio\client.py", line 543, in __await_impl__
    await self.connection.handshake(
  File "C:\Users\***\miniconda3\envs\wiu\lib\site-packages\websockets\asyncio\client.py", line 114, in handshake
    raise self.protocol.handshake_exc
websockets.exceptions.InvalidMessage: did not receive a valid HTTP response

@milk-bottle-liyu
Copy link
Author

In addition, I am working on Windows10 in a conda environment. The installed packages are:

Package           Version
----------------- --------
annotated-types   0.7.0   
anyio             4.9.0   
asttokens         3.0.0   
click             8.1.8   
colorama          0.4.6   
decorator         5.2.1   
exceptiongroup    1.2.2   
executing         2.2.0   
fastapi           0.115.12
h11               0.16.0  
httptools         0.6.4   
idna              3.10    
ipython           8.35.0  
jedi              0.19.2
MarkupSafe        3.0.2
matplotlib-inline 0.1.7
numpy             2.2.5
parso             0.8.4
pip               25.0
prompt_toolkit    3.0.51
pure_eval         0.2.3
pydantic          2.11.3
pydantic_core     2.33.1
Pygments          2.19.1
python-dotenv     1.1.0
PyYAML            6.0.2
setuptools        75.8.0
sniffio           1.3.1
stack-data        0.6.3
starlette         0.46.2
traitlets         5.14.3
typing_extensions 4.13.2
typing-inspection 0.4.0
uvicorn           0.34.2
watchfiles        1.0.5
wcwidth           0.2.13
websocket-client  1.8.0
websockets        15.0.1
Werkzeug          3.1.3
wheel             0.45.1

@aaugustin
Copy link
Member

websockets and postman send the same headers so I don't think we have a problem there.

When connecting using Python code, it seems that the server did not receive any data, as there is no output of log on the server side.

More likely the problem is that your server doesn't actually receive the request from websockets?

I'm sorry, I don't really know how to help you debug this remotely :-(

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants