I have a Flask server with a webhook endpoint for Meraki Alerts ("host_url/endpoint").
The server also has a page which is supposed to display all recieved alerts ("host_url/view").
What I would love to happen is that when Meraki sends a webhook to my endpoint all the clients on "host_url/view" update to show the latest alerts.
I have tried simply polling every few seconds, but even though it works I would like to avoid this solution.
I also tried using websockets, but the standard flask_socketio
implementation requires messages send from the server to be within functions decorated with an @socketio.on("...")
decorator.
E.g.
@socketio.on("connect")
def send_message():
emit("msg")
But since the event that triggers such a message isn't a websocket event in itself I need to be able to send messages outside of a socketio function.
E.g.
def send_message():
emit("msg")
My goal is to have a function send_to_all_clients(data)
that I can use from everywhere in my code and that sends an event that can be recieved by a Javascript event handler.
To send an event to all clients, I recommend taking a look at the “Broadcasting” section of the Flask-SocketIO documentation. Here it is described how you can use socketio.emit(eventName, data)
to send an event, for example from a normal route, so that it can be received by all connected clients.
In the following example, at the push of a button an example event is sent to the webhook, which is then passed on to all clients. Using Postman would certainly be more advisable.
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>