How To Use WebSocket With FastAPI
The Hypertext Transfer Protocol (or HTTP) is one the most used protocols on the internet today. It allows a client to fetch a resource, such as HTML pages and images. This article you are reading now was transmitted via HTTP (actually, its secured form, HTTPS).
The client (usually a browser) requests a resource (an image, a CSS file, etc) to the server, and the server responds with the requested data. It is a strictly unidirectional protocol. A server will only send data when requested by a client.
Open a connection, request what you want, wait for the response, and close the connection. That is the basic of HTTP. It works fine when you are dealing with documents. But when it comes to more “realtime” applications, such as gaming and chats, you start to have some problems with this approach.
Since there is no way to the server to send the client a message when a resource has changed, the client will have to continuously ask the server for the resource data. It wastes resources, as a new connection is created for everything request, even though nothing might have changed. This method is called polling, and although there some methods to minimize it (such as long-polling), they are just workarounds to the problem.
Here is where the idea of WebSocket was born. It allows the TCP connection to be maintained alive, so both the server and client can send data to each other, without the necessity of creating a new connection every time.
It uses HTTP as the initial transport mechanism, but “upgrades” the connection. Then a bidirectional, full-duplex communication channel is created.
Note: if you want to know more about the Websocket protocol, check this article.
It has some advantages over Flask, such as:
- It is fast (as compared with Flask);
- It has automatic docs (OpenAPI);
- It can use async functions;
- It has support for websocket;
- And many more;
It is a relative new development (< 2 years), but it has already 27k stars on Github.
In this tutorial, we are going to create a simple application that updates a chart using WebSocket connection.
Packages we are going to use:
- FastAPI, version 0.63.0, for the backend.
- ReactJS, version 17.0.1, for the frontend.
- Recharts, version 2.0.6, to create beautiful charts.
TL; DR: you can find the complete code in this Github.
The first thing we have to do is to create our backend. To do it, create a folder called
backend. This is where we are going to put all of our files.
$ mkdir backend
$ cd backend
virtualenv and install the FastAPI package:
$ virtualenv websocket
$ source ./websocket/bin/activate
(websocket) $ pip install fastapi "uvicorn[standard]"
uvicornpackage is necessary to create a ASGI server for our application.
Create a file called
run.py and put the following content:
The function must be decorated with the function
app.websocket, so that the FastAPI application knows that this HTTP connection must be upgraded into a WebSocket. This is accomplished by the
After that, we create a loop to continuously receive and send data to the client. If we don’t execute the loop, we connection is closed automatically (and it will be a normal HTTP connection).
To start the server, just run the command:
(websocket)$ uvicorn run:app
We are going to use React to create a simple client that will consume from this websocket and update a chart every time that a new data is received.
First, let’s create a new app with
create-react-app. This will install all the dependencies and configuration we need:
$ yarn create react-app websocket
$ cd websocket
And install the Recharts dependency:
$ yarn add recharts
To connect with our server, we are going to use the WebSocket API. To create a new object, we just need to inform the url that our server is listening to the WebSocket connection:
const ws = new WebSocket('ws://localhost:8000/ws');
To avoid doing this every time, we put it inside the
We set also an interval that will keep sending an echo message to the server each second, to keep the connection alive.
websocket object contains a
onmessage method that will be called every time a new message is received. We then set the component state with the new value, updating the chart.
Note: to avoid keep a large chart, we remove the old data as soon the limit is reached.
And that’s it. The complete code for the component will be something like this:
Now, just run the client with
yarn start and open the browser in the url
localhost:3000. A chart must appear and the data will be updated automatically in your screen.
The HTTP protocol is limited when we need to create a real-time application, as the connection is closed at every request.
To solve this problem, the WebSocket protocol was created, allowing a connection to be kept opened. So both client and server can send messages to each other.
In this tutorial we’ve seen how to setup a WebSocket server using the FastAPI library and consuming it using React.
The complete code is here.