在 Python Flask 中收到 Webhook 时如何更新所有客户端

问题描述 投票:0回答:1

我有一个 Flask 服务器,带有用于 Meraki Alerts 的 Webhook 端点(“host_url/endpoint”)。
服务器还有一个页面应该显示所有收到的警报(“host_url/view”)。

我希望发生的是,当 Meraki 向我的端点发送 Webhook 时,“host_url/view”上的所有客户端都会更新以显示最新警报。

我尝试过每隔几秒简单地轮询一次,但即使它有效,我也想避免使用这种解决方案。

我也尝试过使用 websockets,但标准

flask_socketio
实现要求从服务器发送的消息位于用
@socketio.on("...")
装饰器装饰的函数内。

例如

@socketio.on("connect")
def send_message():
    emit("msg")

但是由于触发此类消息的事件本身不是 websocket 事件,我需要能够在 socketio 函数之外发送消息。

例如

def send_message():
    emit("msg")

我的目标是拥有一个函数

send_to_all_clients(data)
,我可以在代码中的任何地方使用它,并且发送一个可由 Javascript 事件处理程序接收的事件。

python flask long-polling flask-socketio
1个回答
0
投票

要将事件发送给所有客户端,我建议查看 Flask-SocketIO 文档的 “广播” 部分。这里描述了如何使用

socketio.emit(eventName, data)
发送事件(例如从正常路由),以便所有连接的客户端都可以接收该事件。

在以下示例中,按下按钮时,示例事件将发送到 webhook,然后传递给所有客户端。使用 Postman 肯定会更明智。

from flask import (
    Flask, 
    render_template, 
    request
)
from flask_socketio import SocketIO

app = Flask(__name__)
sock = SocketIO(app)

@app.route('/')
def index():
    return render_template('index.html')

def send_to_all_clients(data):
    sock.emit('details', data)

@app.post('/webhook')
def webhook():
    data = request.get_json(force=True)
    send_to_all_clients(data)
    return '', 200

if __name__ == '__main__':
    sock.run(app)
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Index</title>
</head>
<body>
    <button id="snd">Call Webhook</button>
    <pre><output id="out"></output></pre>

    <script 
        src="https://cdn.socket.io/4.7.2/socket.io.min.js" 
        integrity="sha384-mZLF4UVrpi/QTWPA7BjNPEnkIfRFn4ZEO3Qt/HFklTJBj/gBOV8G3HcKn4NfQblz" 
        crossorigin="anonymous"></script>

    <script>
        (function() {
            const sock = io();
            sock.on('details', (...args) => {
                const elem = document.getElementById('out');
                elem.innerText += JSON.stringify(args) + '\n';
            });

            document.getElementById('snd').addEventListener('click', () => {
                const data = {
                    "version": "0.1",
                    "sharedSecret": "secret",
                    "sentAt": "2021-10-07T08:38:40.522804Z",
                    "organizationId": "2930418",
                    "organizationName": "My organization",
                    "organizationUrl": "https://dashboard.meraki.com/o/VjjsAd/manage/organization/overview",
                    "networkId": "N_24329156",
                    "networkName": "Main Office",
                    "networkUrl": "https://n1.meraki.com//n//manage/nodes/list",
                    "networkTags": [],
                    "deviceSerial": "Q234-ABCD-5678",
                    "deviceMac": "00:11:22:33:44:55",
                    "deviceName": "My access point",
                    "deviceUrl": "https://n1.meraki.com//n//manage/nodes/new_list/000000000000",
                    "deviceTags": [
                        "tag1",
                        "tag2"
                    ],
                    "deviceModel": "MR",
                    "alertId": "0000000000000000",
                    "alertType": "APs came up",
                    "alertTypeId": "started_reporting",
                    "alertLevel": "informational",
                    "occurredAt": "2018-02-11T00:00:00.123450Z",
                    "alertData": {}
                };
                fetch('/webhook', {
                    method: 'post', 
                    body: JSON.stringify(data)
                });
            })
        })();
    </script>
</body>
</html>
© www.soinside.com 2019 - 2024. All rights reserved.