上一节,我们分享了WebSockets入门的使用方法,本节,我们在原来的基础上,进行深入的演示。上一节最后我们提到了依赖token或者cookie等。首先我们对上次的代码进行调整。在 FastApi学习之路(三十八)Static Files,我们提到了静态文件的使用,我们按照之前的方法,将上一节中的静态代码抽离出来。
放在了templates下面的webchat.html。
<!DOCTYPE html><html><head><title>Chat</title></head><body><h1>WebSocket 聊天</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>
main里面的代码调整为:
"""
-*- encoding=utf-8 -*-
Time: 2024/7/12 09:41
Author: lc
Email: 15101006331@163.com
File: main.py
"""
from typing import Optional
from fastapi import Cookie, Depends, FastAPI, Request, Query, WebSocket, status
from fastapi.templating import Jinja2Templatesapp = FastAPI()
templates = Jinja2Templates(directory="./templates")@app.get("/")
async def home(request: Request):return templates.TemplateResponse("webchat.html",{"request": request})async def get_cookie_or_token(websocket: WebSocket,session: Optional[str] = Cookie(None),token: Optional[str] = Query(None),
):if session is None and token is None:await websocket.close(code=status.WS_1008_POLICY_VIOLATION)return session or token@app.websocket("item/ws")
async def websocket_endpoint(websocket: WebSocket,cookie_or_token: str = Depends(get_cookie_or_token),
):await websocket.accept()while True:data = await websocket.receive_text()await websocket.send_text(f"Message is: {data}")
但是我们之前的html代码去调试的时候,发现报错,因为我们需要依靠session或者token。那么我们需要对html进行调整。
<!DOCTYPE html>
<html><head><title>Chat</title></head><body><h1>WebSocket Chat</h1><form action="" onsubmit="sendMessage(event)"><label>Token: <input type="text" id="token" autocomplete="off" value="some-key-token"/></label><button onclick="connect(event)">链接</button><hr><label>消息: <input type="text" id="messageText" autocomplete="off"/></label><button>发送</button></form><ul id='messages'></ul><script>var ws = null;function connect(event) {var token = document.getElementById("token")ws = new WebSocket("ws://localhost:8000/items/ws?token=" + token.value);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)};event.preventDefault()}function sendMessage(event) {var input = document.getElementById("messageText")ws.send(input.value)input.value = ''event.preventDefault()}
</script></body>
</html>
其实我们就是增加了带了token。
但是当我们直接点发送时无法发送消息,只有我们先点击链接按钮增加了token之后就可以发送成功了。
这样我们的WebSockets就可以带token来做登录了,但是我们的token呢,只是做了简单的校验。那么我们是不是可以和登录退出放在一起呢。肯定是可以的,我们在下次分享的时候将登录退出分享出来