8

I am using FastAPI with @app.websocket to listen for incoming websockets. How does FastAPI (or Starlette or Uvicorn underneath) do ping/pong heartbeats? Is this configurable? I cannot find it in the documentation at all.

from fastapi import FastAPI, WebSocket

app = FastAPI()

@app.websocket("/")
def ws(websocket: WebSocket):
    pass

fastapi uses starlette, and under the hood it seems to use websockets. websockets.connect by default uses a ping_interval and ping_timeout of 20 seconds, but I can't tell if that is used in FastAPI.

Jonathan
  • 1,864
  • 17
  • 26
  • 4
    the ping pong happens in uvicorn, and there's no current way to configure those values, there's an open issue here : https://github.com/encode/uvicorn/issues/245 , PR welcome ! – euri10 Sep 11 '20 at 13:17
  • @euri10 Thanks for the pointer. I'm glad to know it uses the same 20 second defaults. I would love to do a PR, but right now I still don't understand the internals well enough to know how to pass that. I'll keep digging, thanks for the encouragement. – Jonathan Sep 11 '20 at 15:19
  • @euri10 Just saw https://github.com/encode/uvicorn/pull/1048. Thank you so much, that is perfect. If you want to turn this into an answer, I'll gladly accept it and give you the internet points :) – Jonathan Sep 13 '21 at 15:21
  • 1
    haha thanks for the reminder ! I added an answer that reflects current usage ! – euri10 Sep 13 '21 at 19:29

1 Answers1

5

You can now use the 2 following flags:

  1. --ws-ping-interval <float> - Set the WebSockets ping interval, in seconds. Please note that this can be used only with the default websockets protocol.
  2. --ws-ping-timeout <float> - Set the WebSockets ping timeout, in seconds. Please note that this can be used only with the default websockets protocol.
Sam Mason
  • 15,216
  • 1
  • 41
  • 60
euri10
  • 2,446
  • 3
  • 24
  • 46
  • Is there a way to do this programmatically in the code? Somewhere in await websocket.accept() – Sayanc2000 Nov 14 '21 at 08:54
  • 2
    @Sayanc2000 When running uvicorn, you can pass them to the `run` method, e.g. `uvicorn.run('app:app', ws_ping_interval=300, ws_ping_timeout=300)` – TJR Jan 17 '22 at 11:00
  • `uvicorn main:app --ws-ping-timeout 2.0` expected to terminate WS in 2 sec but not working for me. Its 32s – Prashant Sep 01 '23 at 21:01