diff --git a/docs/img/tutorial/websockets/image01.png b/docs/img/tutorial/websockets/image01.png new file mode 100644 index 000000000..c6de53b56 Binary files /dev/null and b/docs/img/tutorial/websockets/image01.png differ diff --git a/docs/img/tutorial/websockets/image02.png b/docs/img/tutorial/websockets/image02.png new file mode 100644 index 000000000..84e2d6ad7 Binary files /dev/null and b/docs/img/tutorial/websockets/image02.png differ diff --git a/docs/img/tutorial/websockets/image03.png b/docs/img/tutorial/websockets/image03.png new file mode 100644 index 000000000..31b2110af Binary files /dev/null and b/docs/img/tutorial/websockets/image03.png differ diff --git a/docs/img/tutorial/websockets/image04.png b/docs/img/tutorial/websockets/image04.png new file mode 100644 index 000000000..7fed0b03b Binary files /dev/null and b/docs/img/tutorial/websockets/image04.png differ diff --git a/docs/src/websockets/tutorial001.py b/docs/src/websockets/tutorial001.py new file mode 100644 index 000000000..2713550d3 --- /dev/null +++ b/docs/src/websockets/tutorial001.py @@ -0,0 +1,53 @@ +from fastapi import FastAPI +from starlette.responses import HTMLResponse +from starlette.websockets import WebSocket + +app = FastAPI() + +html = """ + + + + Chat + + +

WebSocket Chat

+
+ + +
+ + + + +""" + + +@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() diff --git a/docs/tutorial/websockets.md b/docs/tutorial/websockets.md new file mode 100644 index 000000000..703f57aa1 --- /dev/null +++ b/docs/tutorial/websockets.md @@ -0,0 +1,93 @@ + +You can use WebSockets 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 Starlette. + + 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: + +* Applications (`websocket_route`). +* The `WebSocket` class. +* Class-based WebSocket handling. + + +## Test it + +If your file is named `main.py`, run your application with: + +```bash +uvicorn main:app --debug +``` + +Open your browser at http://127.0.0.1:8000. + +You will see a simple page like: + + + +You can type messages in the input box, and send them: + + + +And your **FastAPI** application with WebSockets will respond back: + + + +You can send (and receive) many messages: + + + +And all of them will use the same WebSocket connection. diff --git a/mkdocs.yml b/mkdocs.yml index 432a23051..2760194af 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -62,6 +62,7 @@ nav: - Sub Applications - Behind a Proxy: 'tutorial/sub-applications-proxy.md' - Application Configuration: 'tutorial/application-configuration.md' - GraphQL: 'tutorial/graphql.md' + - WebSockets: 'tutorial/websockets.md' - Debugging: 'tutorial/debugging.md' - Concurrency and async / await: 'async.md' - Deployment: 'deployment.md'