mirror of https://github.com/tiangolo/fastapi.git
✨ Add docs for WebSockets (#62)
This commit is contained in:
parent
e2723e8480
commit
bbd2198fa2
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 21 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 30 KiB |
|
|
@ -0,0 +1,53 @@
|
||||||
|
from fastapi import FastAPI
|
||||||
|
from starlette.responses import HTMLResponse
|
||||||
|
from starlette.websockets import WebSocket
|
||||||
|
|
||||||
|
app = FastAPI()
|
||||||
|
|
||||||
|
html = """
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Chat</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>WebSocket Chat</h1>
|
||||||
|
<form action="" onsubmit="sendMessage(event)">
|
||||||
|
<input type="text" id="messageText" autocomplete="off"/>
|
||||||
|
<button>Send</button>
|
||||||
|
</form>
|
||||||
|
<ul id='messages'>
|
||||||
|
</ul>
|
||||||
|
<script>
|
||||||
|
var ws = new WebSocket("ws://localhost:8000/ws");
|
||||||
|
ws.onmessage = function(event) {
|
||||||
|
var messages = document.getElementById('messages')
|
||||||
|
var message = document.createElement('li')
|
||||||
|
var content = document.createTextNode(event.data)
|
||||||
|
message.appendChild(content)
|
||||||
|
messages.appendChild(message)
|
||||||
|
};
|
||||||
|
function sendMessage(event) {
|
||||||
|
var input = document.getElementById("messageText")
|
||||||
|
ws.send(input.value)
|
||||||
|
input.value = ''
|
||||||
|
event.preventDefault()
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/")
|
||||||
|
async def get():
|
||||||
|
return HTMLResponse(html)
|
||||||
|
|
||||||
|
|
||||||
|
@app.websocket_route("/ws")
|
||||||
|
async def websocket_endpoint(websocket: WebSocket):
|
||||||
|
await websocket.accept()
|
||||||
|
while True:
|
||||||
|
data = await websocket.receive_text()
|
||||||
|
await websocket.send_text(f"Message text was: {data}")
|
||||||
|
await websocket.close()
|
||||||
|
|
@ -0,0 +1,93 @@
|
||||||
|
|
||||||
|
You can use <a href="https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API" target="_blank">WebSockets</a> with **FastAPI**.
|
||||||
|
|
||||||
|
## WebSockets client
|
||||||
|
|
||||||
|
### In production
|
||||||
|
|
||||||
|
In your production system, you probably have a frontend created with a modern framework like React, Vue.js or Angular.
|
||||||
|
|
||||||
|
And to communicate using WebSockets with your backend you would probably use your frontend's utilities.
|
||||||
|
|
||||||
|
Or you might have a native mobile application that communicates with your WebSocket backend directly, in native code.
|
||||||
|
|
||||||
|
Or you might have any other way to communicate with the WebSocket endpoint.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
But for this example, we'll use a very simple HTML document with some JavaScript, all inside a long string.
|
||||||
|
|
||||||
|
This, of course, is not optimal and you wouldn't use it for production.
|
||||||
|
|
||||||
|
In production you would have one of the options above.
|
||||||
|
|
||||||
|
But it's the simplest way to focus on the server-side of WebSockets and have a working example:
|
||||||
|
|
||||||
|
```Python hl_lines="2 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 42 43 44"
|
||||||
|
{!./src/websockets/tutorial001.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Create a `websocket_route`
|
||||||
|
|
||||||
|
In your **FastAPI** application, create a `websocket_route`:
|
||||||
|
|
||||||
|
```Python hl_lines="3 47 48"
|
||||||
|
{!./src/websockets/tutorial001.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
!!! tip
|
||||||
|
In this example we are importing `WebSocket` from `starlette.websockets` to use it in the type declaration in the WebSocket route function.
|
||||||
|
|
||||||
|
That is not required, but it's recommended as it will provide you completion and checks inside the function.
|
||||||
|
|
||||||
|
|
||||||
|
!!! info
|
||||||
|
This `websocket_route` we are using comes directly from <a href="https://www.starlette.io/applications/" target="_blank">Starlette</a>.
|
||||||
|
|
||||||
|
That's why the naming convention is not the same as with other API path operations (`get`, `post`, etc).
|
||||||
|
|
||||||
|
|
||||||
|
## Await for messages and send messages
|
||||||
|
|
||||||
|
In your WebSocket route you can `await` for messages and send messages.
|
||||||
|
|
||||||
|
```Python hl_lines="49 50 51 52 53"
|
||||||
|
{!./src/websockets/tutorial001.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
You can receive and send binary, text, and JSON data.
|
||||||
|
|
||||||
|
To learn more about the options, check Starlette's documentation for:
|
||||||
|
|
||||||
|
* <a href="https://www.starlette.io/applications/" target="_blank">Applications (`websocket_route`)</a>.
|
||||||
|
* <a href="https://www.starlette.io/websockets/" target="_blank">The `WebSocket` class</a>.
|
||||||
|
* <a href="https://www.starlette.io/endpoints/#websocketendpoint" target="_blank">Class-based WebSocket handling</a>.
|
||||||
|
|
||||||
|
|
||||||
|
## Test it
|
||||||
|
|
||||||
|
If your file is named `main.py`, run your application with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
uvicorn main:app --debug
|
||||||
|
```
|
||||||
|
|
||||||
|
Open your browser at <a href="http://127.0.0.1:8000" target="_blank">http://127.0.0.1:8000</a>.
|
||||||
|
|
||||||
|
You will see a simple page like:
|
||||||
|
|
||||||
|
<img src="/img/tutorial/websockets/image01.png">
|
||||||
|
|
||||||
|
You can type messages in the input box, and send them:
|
||||||
|
|
||||||
|
<img src="/img/tutorial/websockets/image02.png">
|
||||||
|
|
||||||
|
And your **FastAPI** application with WebSockets will respond back:
|
||||||
|
|
||||||
|
<img src="/img/tutorial/websockets/image03.png">
|
||||||
|
|
||||||
|
You can send (and receive) many messages:
|
||||||
|
|
||||||
|
<img src="/img/tutorial/websockets/image04.png">
|
||||||
|
|
||||||
|
And all of them will use the same WebSocket connection.
|
||||||
|
|
@ -62,6 +62,7 @@ nav:
|
||||||
- Sub Applications - Behind a Proxy: 'tutorial/sub-applications-proxy.md'
|
- Sub Applications - Behind a Proxy: 'tutorial/sub-applications-proxy.md'
|
||||||
- Application Configuration: 'tutorial/application-configuration.md'
|
- Application Configuration: 'tutorial/application-configuration.md'
|
||||||
- GraphQL: 'tutorial/graphql.md'
|
- GraphQL: 'tutorial/graphql.md'
|
||||||
|
- WebSockets: 'tutorial/websockets.md'
|
||||||
- Debugging: 'tutorial/debugging.md'
|
- Debugging: 'tutorial/debugging.md'
|
||||||
- Concurrency and async / await: 'async.md'
|
- Concurrency and async / await: 'async.md'
|
||||||
- Deployment: 'deployment.md'
|
- Deployment: 'deployment.md'
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue