如何解决Quart和WebSocket:如何仅将数据发送给选定的用户私人消息
我知道如何广播,但我无法定位客户。 这是我的脚本:
import json
import trio
from quart import render_template,websocket,render_template_string
from quart_trio import QuartTrio
from quart_auth import current_user,login_required
from quart_auth import AuthUser,login_user,logout_user,AuthManager
import random
connections = set()
app = QuartTrio(__name__)
AuthManager(app)
app.secret_key = "secret key"
@app.route("/")
async def index():
clean_guy = await current_user.is_authenticated
if not clean_guy:
fake_ID = random.randrange(0,9999) #quick dirty to test
login_user(AuthUser(fake_ID))
return await render_template_string("{{ current_user.__dict__ }}")
return await render_template_string("{{ current_user.__dict__ }}")
@app.websocket("/ws")
async def chat():
try:
connections.add(websocket._get_current_object())
async with trio.open_nursery() as nursery:
nursery.start_soon(heartbeat)
while True:
message = await websocket.receive()
await broadcast(message)
finally:
connections.remove(websocket._get_current_object())
async def broadcast(message):
for connection in connections:
await connection.send(json.dumps({"type": "message","value": message}))
async def heartbeat():
while True:
await trio.sleep(1)
await websocket.send(json.dumps({"type": "heartbeat"}))
if __name__ == '__main__':
app.run(host='0.0.0.0',port=5000)
这是我的模板:
<div>
<div>
<ul>
</ul>
</div>
<form>
<input type="text">
<button type="submit">Send</button>
</form>
</div>
<script type="text/javascript">
document.addEventListener("DOMContentLoaded",function() {
const ws = new WebSocket(`ws://${window.location.host}/ws`);
ws.onmessage = function(event) {
const data = JSON.parse(event.data);
if (data.type === "message") {
const ulDOM = document.querySelectorAll("ul")[0];
const liDOM = document.createElement("li");
liDOM.innerText = data.value;
ulDOM.appendChild(liDOM);
}
}
document.querySelectorAll("form")[0].onsubmit = function(event) {
event.preventDefault();
const inputDOM = document.querySelectorAll("input")[0];
ws.send(inputDOM.value);
inputDOM.value = "";
return false;
};
});
</script>
还有一个问题: 如果我在脚本中使用它:
return await render_template("{{ current_user.__dict__ }}")
即使我在模板中添加了 {{current_user。 dict }} ,我也无法将其与我的jinja模板一起显示。
我还注意到:
- 使用mozilla:我得到稳定的东西,例如
{'_ auth_id':9635,'action':
} - 使用chrome:每次刷新时都会更改,看起来像
{'_ auth_id':529,'action':
}
我需要显示作者,目的地,带有发送按钮的输入,以及如何修复模板?
是否还可以通过curl或websocat通过帖子向目标用户发送消息?该怎么做?
解决方法
Quart-Auth使用cookie来标识每个请求/ websocket-request上的用户,因此,如果请求通过了身份验证,则始终可以从current_user中获取用户的身份。然后,根据您的需要,您需要将websocket连接映射到每个用户(以便您可以定位消息),因此连接映射应该是连接字典,例如
import random
from collections import defaultdict
from quart import request,websocket
from quart_trio import QuartTrio
from quart_auth import (
AuthUser,current_user,login_required,login_user,logout_user,AuthManager
)
connections = defaultdict(set)
app = QuartTrio(__name__)
AuthManager(app)
app.secret_key = "secret key"
@app.route("/login",methods=["POST"])
async def login():
# Figure out who the user is,user_id = random.randrange(0,9999)
login_user(AuthUser(fake_ID))
return {}
@app.websocket("/ws")
@login_required
async def chat():
user_id = await current_user.auth_id
try:
connections[user_id].add(websocket._get_current_object())
while True:
data = await websocket.receive_json()
await broadcast(data["message"])
finally:
connections[user_id].remove(websocket._get_current_object())
@app.route('/broadcast',methods=['POST'])
@login_required
async def send_broadcast():
data = await request.get_json()
await broadcast(data["message"],data.get("target_id"))
return {}
async def broadcast(message,target = None):
if target is None:
for user_connections in connections.values():
for connection in user_connections:
await connection.send_json({"type": "message","value": message})
else:
for connection in connections[target]:
await connection.send_json({"type": "message","value": message})
if __name__ == '__main__':
app.run(host='0.0.0.0',port=5000)
然后,您可以将只是消息/broadcast
的JSON或具有ID的消息发送给{"message": "something"}
,以专门针对某人{"message": "something for user 2","target_id": 2}
。还请注意,@login_required
装饰器可确保仅对已登录的用户调用路由处理程序。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。