Python : Flask et SocketIO
Un chat très simple
https://codeburst.io/building-your-first-chat-application-using-flask-in-7-minutes-f98de4adfa5d
Voir les commentaires. On commence par le script Flask: <syntaxhighlight lang='python'>
- !/usr/bin/env python3
- coding: utf-8
from flask import Flask, render_template from flask_socketio import SocketIO
- !---------- juchat.py ----------
- https://codeburst.io/building-your-first-chat-application-using-flask-in-7-minutes-f98de4adfa5d
- --------------------------------!
- ----------! FUNC
- ----------! MAIN
- Déclaration de l'application
app = Flask(__name__)
- Utilisée pour signer les cookies
app.config['SECRET_KEY'] = 'eech8ahNohzeefaJ'
- Déclaration de l'application SocketIO
socketio = SocketIO(app)
@app.route('/') def sessions():
return render_template('sessions.html')
def messageReceived(methods=['GET', 'POST']):
print('Message was received !')
""" Partie socketio : SocketIo est une implémentation de WebSocket en java, cross-platform, qui permet d'échanger en bidirectionnel au niveau de la couche application. Pour recevoir des messages websocket du client, l'application définit des event handlers en utilisant le décorateur socketio.on et elle peut émettre et recevoir des réponses au client connecté avec les fonctions send() et emit() """
@socketio.on('my event') def handle_my_custom_event(json, methods=['GET', 'POST']):
print('Received my event: ' + str(json)) socketio.emit('my response', json, callback=messageReceived)
""" Quand 'my event' est trigger, la vue handle_my_custom_event reçoit d'abord l'objet json, le print et plus tard l'envoie à l'event 'my response'. 'callback' est une technique pour savoir si le message est reçu par le serveur et appelle la fonction 'message received'. """
if __name__ == '__main__':
socketio.run(app, debug=True)
</syntaxhighlight>
Et le template:
<syntaxhighlight lang='html'>
<!DOCTYPE html> <html lang="en"> <head> <title>Flask_Chat_App</title> </head> <body>
No message yet..
<form action="" method="POST"> <input type="text" class="username" placeholder="User Name"/> <input type="text" class="message" placeholder="Messages"/> <input type="submit"/> </form>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.7.3/socket.io.min.js"></script>
<script type="text/javascript"> var socket = io.connect('http://' + document.domain + ':' + location.port);
/* connect, disconnect, message, json sont des evnets prédéfinis par SocketIO connect et disconnect sont explicites, message envoie un str / json, et json envoie un payload json sous la forme d'un dictionnaire Python.
Pour envoyer des events, un serveur Flask peut utiliser les fonctions send() et emit() de Flask-SocketIO. La fonction send() envoie un message standard (str / json) et emit() fait la même chose avec avec un nom d'event customisé. */ socket.on( 'connect', function() { socket.emit( 'my event', { data: 'User Connected' } )
/* Après POST du form, un event e est passé en argument. PreventDefault est appellé poour empêcher de submit le form. On prend ensuite les valeurs du username et du message. Ces valeurs sont envoyées dans la fonction emit() à l'event custom my event (dans notre script Flask). Après ça, le field message est vidé pour permettre d'envoyer plus de messages. */
var form = $( 'form' ).on( 'submit', function( e ) { e.preventDefault() let user_name = $( 'input.username' ).val() let user_input = $( 'input.message' ).val() socket.emit( 'my event', { user_name : user_name, message : user_input } ) $( 'input.message' ).val( ).focus() } ) } )
/* Une fois le message envoyé à l'event, on doit rendre le message reçu sur la page HTML. Sur une réponse, dès que le message est reçu on le passe à la classe message_holder (on en profite pour enlever le 'no message yet') et nos messages sont ajoutés aux précédents. */ socket.on( 'my response', function( msg ) { console.log( msg ) if( typeof msg.user_name !== 'undefined' ) { $( 'h3' ).remove()
$( 'div.message_holder' ).append( '
' )
} }) </script>
</body> </html>
</syntaxhighlight>