WebSockets

When defining WebSockets, you normally declare a parameter of type WebSocket and with it you can read data from the client and send data to it.

It is provided directly by Starlette, but you can import it from fastapi:

  1. from fastapi import WebSocket

Tip

When you want to define dependencies that should be compatible with both HTTP and WebSockets, you can define a parameter that takes an HTTPConnection instead of a Request or a WebSocket.

fastapi.WebSocket

  1. WebSocket(scope, receive, send)

Bases: [HTTPConnection](https:/fastapi.tiangolo.com/zh/reference/httpconnection/#fastapi.requests.HTTPConnection "starlette.requests.HTTPConnection")

PARAMETERDESCRIPTION
scope

TYPE: Scope

receive

TYPE: Receive

send

TYPE: Send

Source code in starlette/websockets.py

  1. 22
  2. 23
  3. 24
  4. 25
  5. 26
  6. 27
  7. 28
  1. def init(self, scope: Scope, receive: Receive, send: Send) -> None:
  2. super().init(scope)
  3. assert scope[type] == websocket
  4. self._receive = receive
  5. self._send = send
  6. self.client_state = WebSocketState.CONNECTING
  7. self.application_state = WebSocketState.CONNECTING

scope instance-attribute

  1. scope = scope

app property

  1. app

url property

  1. url

base_url property

  1. base_url

headers property

  1. headers

query_params property

  1. query_params

path_params property

  1. path_params

cookies property

  1. cookies

client property

  1. client

state property

  1. state

client_state instance-attribute

  1. client_state = CONNECTING

application_state instance-attribute

  1. application_state = CONNECTING

url_for

  1. url_for(__name, **path_params)
PARAMETERDESCRIPTION
__name

TYPE: str

**path_params

TYPE: Any DEFAULT: {}

Source code in starlette/requests.py

  1. 176
  2. 177
  3. 178
  4. 179
  1. def url_for(self, name: str, **path_params: typing.Any) -> URL:
  2. router: Router = self.scope[router]
  3. url_path = router.url_path_for(name, **path_params)
  4. return url_path.make_absolute_url(base_url=self.base_url)

receive async

  1. receive()

Receive ASGI websocket messages, ensuring valid state transitions.

Source code in starlette/websockets.py

  1. 30
  2. 31
  3. 32
  4. 33
  5. 34
  6. 35
  7. 36
  8. 37
  9. 38
  10. 39
  11. 40
  12. 41
  13. 42
  14. 43
  15. 44
  16. 45
  17. 46
  18. 47
  19. 48
  20. 49
  21. 50
  22. 51
  23. 52
  24. 53
  25. 54
  26. 55
  27. 56
  28. 57
  29. 58
  1. async def receive(self) -> Message:
  2. “””
  3. Receive ASGI websocket messages, ensuring valid state transitions.
  4. “””
  5. if self.client_state == WebSocketState.CONNECTING:
  6. message = await self._receive()
  7. message_type = message[type]
  8. if message_type != websocket.connect:
  9. raise RuntimeError(
  10. Expected ASGI message websocket.connect”,
  11. fbut got {message_type!r}
  12. )
  13. self.client_state = WebSocketState.CONNECTED
  14. return message
  15. elif self.client_state == WebSocketState.CONNECTED:
  16. message = await self._receive()
  17. message_type = message[type]
  18. if message_type not in {websocket.receive, websocket.disconnect}:
  19. raise RuntimeError(
  20. Expected ASGI message websocket.receive or
  21. f‘“websocket.disconnect”, but got {message_type!r}
  22. )
  23. if message_type == websocket.disconnect:
  24. self.client_state = WebSocketState.DISCONNECTED
  25. return message
  26. else:
  27. raise RuntimeError(
  28. Cannot call receive once a disconnect message has been received.’
  29. )

send async

  1. send(message)

Send ASGI websocket messages, ensuring valid state transitions.

PARAMETERDESCRIPTION
message

TYPE: Message

Source code in starlette/websockets.py

  1. 60
  2. 61
  3. 62
  4. 63
  5. 64
  6. 65
  7. 66
  8. 67
  9. 68
  10. 69
  11. 70
  12. 71
  13. 72
  14. 73
  15. 74
  16. 75
  17. 76
  18. 77
  19. 78
  20. 79
  21. 80
  22. 81
  23. 82
  24. 83
  25. 84
  26. 85
  27. 86
  28. 87
  1. async def send(self, message: Message) -> None:
  2. “””
  3. Send ASGI websocket messages, ensuring valid state transitions.
  4. “””
  5. if self.application_state == WebSocketState.CONNECTING:
  6. message_type = message[type]
  7. if message_type not in {websocket.accept, websocket.close}:
  8. raise RuntimeError(
  9. Expected ASGI message websocket.accept or
  10. f‘“websocket.close”, but got {message_type!r}
  11. )
  12. if message_type == websocket.close:
  13. self.application_state = WebSocketState.DISCONNECTED
  14. else:
  15. self.application_state = WebSocketState.CONNECTED
  16. await self._send(message)
  17. elif self.application_state == WebSocketState.CONNECTED:
  18. message_type = message[type]
  19. if message_type not in {websocket.send, websocket.close}:
  20. raise RuntimeError(
  21. Expected ASGI message websocket.send or websocket.close”,
  22. fbut got {message_type!r}
  23. )
  24. if message_type == websocket.close:
  25. self.application_state = WebSocketState.DISCONNECTED
  26. await self._send(message)
  27. else:
  28. raise RuntimeError(Cannot call send once a close message has been sent.’)

accept async

  1. accept(subprotocol=None, headers=None)
PARAMETERDESCRIPTION
subprotocol

TYPE: Optional[str] DEFAULT: None

headers

TYPE: Optional[Iterable[Tuple[bytes, bytes]]] DEFAULT: None

Source code in starlette/websockets.py

  1. 89
  2. 90
  3. 91
  4. 92
  5. 93
  6. 94
  7. 95
  8. 96
  9. 97
  10. 98
  11. 99
  12. 100
  13. 101
  1. async def accept(
  2. self,
  3. subprotocol: typing.Optional[str] = None,
  4. headers: typing.Optional[typing.Iterable[typing.Tuple[bytes, bytes]]] = None,
  5. ) -> None:
  6. headers = headers or []
  7. if self.client_state == WebSocketState.CONNECTING:
  8. # If we haven’t yet seen the ‘connect’ message, then wait for it first.
  9. await self.receive()
  10. await self.send(
  11. {type: websocket.accept, subprotocol: subprotocol, headers: headers}
  12. )

receive_text async

  1. receive_text()

Source code in starlette/websockets.py

  1. 107
  2. 108
  3. 109
  4. 110
  5. 111
  6. 112
  7. 113
  8. 114
  1. async def receive_text(self) -> str:
  2. if self.application_state != WebSocketState.CONNECTED:
  3. raise RuntimeError(
  4. WebSocket is not connected. Need to call accept first.’
  5. )
  6. message = await self.receive()
  7. self._raise_on_disconnect(message)
  8. return message[text]

receive_bytes async

  1. receive_bytes()

Source code in starlette/websockets.py

  1. 116
  2. 117
  3. 118
  4. 119
  5. 120
  6. 121
  7. 122
  8. 123
  1. async def receive_bytes(self) -> bytes:
  2. if self.application_state != WebSocketState.CONNECTED:
  3. raise RuntimeError(
  4. WebSocket is not connected. Need to call accept first.’
  5. )
  6. message = await self.receive()
  7. self._raise_on_disconnect(message)
  8. return message[bytes]

receive_json async

  1. receive_json(mode='text')
PARAMETERDESCRIPTION
mode

TYPE: str DEFAULT: ‘text’

Source code in starlette/websockets.py

  1. 125
  2. 126
  3. 127
  4. 128
  5. 129
  6. 130
  7. 131
  8. 132
  9. 133
  10. 134
  11. 135
  12. 136
  13. 137
  14. 138
  15. 139
  1. async def receive_json(self, mode: str = text) -> typing.Any:
  2. if mode not in {text, binary}:
  3. raise RuntimeError(The mode argument should be text or binary”.’)
  4. if self.application_state != WebSocketState.CONNECTED:
  5. raise RuntimeError(
  6. WebSocket is not connected. Need to call accept first.’
  7. )
  8. message = await self.receive()
  9. self._raise_on_disconnect(message)
  10. if mode == text:
  11. text = message[text]
  12. else:
  13. text = message[bytes].decode(utf-8)
  14. return json.loads(text)

iter_text async

  1. iter_text()

Source code in starlette/websockets.py

  1. 141
  2. 142
  3. 143
  4. 144
  5. 145
  6. 146
  1. async def iter_text(self) -> typing.AsyncIterator[str]:
  2. try:
  3. while True:
  4. yield await self.receive_text()
  5. except WebSocketDisconnect:
  6. pass

iter_bytes async

  1. iter_bytes()

Source code in starlette/websockets.py

  1. 148
  2. 149
  3. 150
  4. 151
  5. 152
  6. 153
  1. async def iter_bytes(self) -> typing.AsyncIterator[bytes]:
  2. try:
  3. while True:
  4. yield await self.receive_bytes()
  5. except WebSocketDisconnect:
  6. pass

iter_json async

  1. iter_json()

Source code in starlette/websockets.py

  1. 155
  2. 156
  3. 157
  4. 158
  5. 159
  6. 160
  1. async def iter_json(self) -> typing.AsyncIterator[typing.Any]:
  2. try:
  3. while True:
  4. yield await self.receive_json()
  5. except WebSocketDisconnect:
  6. pass

send_text async

  1. send_text(data)
PARAMETERDESCRIPTION
data

TYPE: str

Source code in starlette/websockets.py

  1. 162
  2. 163
  1. async def send_text(self, data: str) -> None:
  2. await self.send({type: websocket.send, text: data})

send_bytes async

  1. send_bytes(data)
PARAMETERDESCRIPTION
data

TYPE: bytes

Source code in starlette/websockets.py

  1. 165
  2. 166
  1. async def send_bytes(self, data: bytes) -> None:
  2. await self.send({type: websocket.send, bytes: data})

send_json async

  1. send_json(data, mode='text')
PARAMETERDESCRIPTION
data

TYPE: Any

mode

TYPE: str DEFAULT: ‘text’

Source code in starlette/websockets.py

  1. 168
  2. 169
  3. 170
  4. 171
  5. 172
  6. 173
  7. 174
  8. 175
  1. async def send_json(self, data: typing.Any, mode: str = text) -> None:
  2. if mode not in {text, binary}:
  3. raise RuntimeError(The mode argument should be text or binary”.’)
  4. text = json.dumps(data, separators=(“,”, “:”))
  5. if mode == text:
  6. await self.send({type: websocket.send, text: text})
  7. else:
  8. await self.send({type: websocket.send, bytes: text.encode(utf-8)})

close async

  1. close(code=1000, reason=None)
PARAMETERDESCRIPTION
code

TYPE: int DEFAULT: 1000

reason

TYPE: Optional[str] DEFAULT: None

Source code in starlette/websockets.py

  1. 177
  2. 178
  3. 179
  4. 180
  5. 181
  6. 182
  1. async def close(
  2. self, code: int = 1000, reason: typing.Optional[str] = None
  3. ) -> None:
  4. await self.send(
  5. {type: websocket.close, code: code, reason: reason or “”}
  6. )

When a client disconnects, a WebSocketDisconnect exception is raised, you can catch it.

You can import it directly form fastapi:

  1. from fastapi import WebSocketDisconnect

fastapi.WebSocketDisconnect

  1. WebSocketDisconnect(code=1000, reason=None)

Bases: Exception

PARAMETERDESCRIPTION
code

TYPE: int DEFAULT: 1000

reason

TYPE: Optional[str] DEFAULT: None

Source code in starlette/websockets.py

  1. 16
  2. 17
  3. 18
  1. def init(self, code: int = 1000, reason: typing.Optional[str] = None) -> None:
  2. self.code = code
  3. self.reason = reason or “”

code instance-attribute

  1. code = code

reason instance-attribute

  1. reason = reason or ''

WebSockets - additional classes

Additional classes for handling WebSockets.

Provided directly by Starlette, but you can import it from fastapi:

  1. from fastapi.websockets import WebSocketDisconnect, WebSocketState

fastapi.websockets.WebSocketDisconnect

  1. WebSocketDisconnect(code=1000, reason=None)

Bases: Exception

PARAMETERDESCRIPTION
code

TYPE: int DEFAULT: 1000

reason

TYPE: Optional[str] DEFAULT: None

Source code in starlette/websockets.py

  1. 16
  2. 17
  3. 18
  1. def init(self, code: int = 1000, reason: typing.Optional[str] = None) -> None:
  2. self.code = code
  3. self.reason = reason or “”

code instance-attribute

  1. code = code

reason instance-attribute

  1. reason = reason or ''

fastapi.websockets.WebSocketState

Bases: Enum

CONNECTING class-attribute instance-attribute

  1. CONNECTING = 0

CONNECTED class-attribute instance-attribute

  1. CONNECTED = 1

DISCONNECTED class-attribute instance-attribute

  1. DISCONNECTED = 2