FastAPI - Websockets

WebSocket 是客户端和服务器之间的持久连接,用于在两者之间提供双向、全双工 通信。 通过单个 TCP/IP 套接字连接在 HTTP 上进行通信。 它可以看作是 HTTP 的升级,而不是一个协议本身。

HTTP 的局限性之一是它是一种严格的半双工或单向协议。 另一方面,使用 WebSockets,我们可以发送基于消息的数据,与 UDP 类似,但具有 TCP 的可靠性。 WebSocket 使用 HTTP 作为初始传输机制,但在收到 HTTP 响应后保持 TCP 连接。 同一个连接对象,它可以用于客户端和服务器之间的双向通信。 因此,可以使用 WebSocket API 构建实时应用程序。

FastAPI 通过 FastAPI 模块中的 WebSocket 类支持 WebSockets。 以下示例演示了 WebSocket 在 FastAPI 应用程序中的功能。

首先我们有一个index() 函数来渲染一个模板(socket.html)。 它绑定到"/"路由。 HTML 文件 socket.html 位于"templates"文件夹中。

main.py

from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse
from fastapi.templating import Jinja2Templates
templates = Jinja2Templates(directory="templates")
from fastapi.staticfiles import StaticFiles
app = FastAPI()
app.mount("/static", StaticFiles(directory="static"), name="static")
@app.get("/", response_class=HTMLResponse)
async def index(request: Request):
   return templates.TemplateResponse("socket.html", {"request": request})

模板文件呈现一个文本框和一个按钮。

socket.html

<!DOCTYPE html>
<html>
   <head>
      <title>Chat</title>
      <script src="{{ url_for('static', path='ws.js') }}"></script>
   </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>
   </body>
</html>

在 socket.html 中,调用了在表单提交时执行的 JavaScript 函数。 因此,为了服务 JavaScript,首先安装"static"文件夹。 JavaScript 文件 ws.js 位于"static"文件夹中。

ws.js

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()
}

加载 JavaScript 代码时,它会创建一个监听"ws://localhost:8000/ws"的 websocket。 sendMessage() 函数将输入消息定向到 WebSocket URL。

此路由调用应用程序代码中的 websocket_endpoint() 函数。 传入的连接请求被接受,传入的消息在客户端浏览器上回显。 将以下代码添加到 main.py。

from fastapi import WebSocket
@app.websocket("/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}")

保存FastAPI代码文件(main.py)、模板(socket.html)和JavaScript文件(ws.js)。 运行 Uvicorn 服务器并访问 http://localhost:8000/ 以呈现如下所示的聊天窗口 −

FastAPI Websockets

键入特定文本,然后按 Send 发送按钮。 输入消息将通过 websocket 在浏览器上重定向。

FastAPI Websockets