chat python ¶
See also
https://github.com/dunglas/mercure/blob/master/examples/chat/requirements.txt ¶
Flask>=1.1.2
PyJWT>=1.7.1
uritemplate>=3.0.1
gunicorn>=20.0.4
https://github.com/dunglas/mercure/blob/master/examples/chat/templates/chat.html ¶
{% extends "layout.html" %}
{% block content %}
<section class="section" id="chat">
<div class="columns">
<div class="column is-three-quarters">
<div class="box">
<template id="message">
<div><strong class="username">Kévin</strong>: <span class="msg"></span></div>
</template>
<div id="messages"></div>
<form>
<div class="field has-addons">
<div class="control is-expanded">
<input name="message" placeholder="Your message..." autocomplete="off" required
class="input is-small is-fullwidth">
</div>
<div class="control">
<button class="button is-primary is-small">Post</button>
</div>
</div>
</form>
</div>
</div>
<div class="column">
<div class="panel">
<p class="panel-heading">Online</p>
<template id="online-user">
<div class="panel-block">
<span class="panel-icon">
<i class="fas fa-user" aria-hidden="true"></i>
</span>
<span class="username"></span>
</div>
</template>
<div class="panel-block is-active">
<span class="panel-icon">
<i class="fas fa-smile" aria-hidden="true"></i>
</span>
<span id="username" title="This is you"></span>
</div>
<div id="user-list"></div>
</div>
</div>
</div>
</section>
<script type="application/json" id="config">{{ config|tojson|safe }}</script>
<script src="/static/chat.js"></script>
{% endblock %}
https://github.com/dunglas/mercure/blob/master/examples/chat/main.py ¶
# -*- coding: utf-8 -*-
"""A minimalist chat system, using the Flask microframework to handle cookie authentication
Install:
pip install -r requirements.txt
Run (prod):
gunicorn chat:app
Run (dev):
FLASK_APP=chat.py FLASK_DEBUG=1 flask run
Deploy on Heroku:
heroku login
heroku config:set HUB_URL=https://demo.mercure.rocks/.well-known/mercure
heroku config:set COOKIE_DOMAIN=.mercure.rocks
git subtree push --prefix examples/chat-python-flask heroku master
Environment variables:
JWT_KEY: the JWT key to use (must be shared with the Mercure hub)
HUB_URL: the URL of the Mercure hub (default: http://localhost:3000/.well-known/mercure)
COOKIE_DOMAIN: the cookie domain (default: None)
"""
from flask import Flask, make_response, request, render_template, abort
import jwt
import os
import json
from uritemplate import expand
HUB_URL = os.environ.get(
'HUB_URL', 'http://localhost:3000/.well-known/mercure')
JWT_KEY = os.environ.get('JWT_KEY', '!ChangeMe!')
MESSAGE_URI_TEMPLATE = os.environ.get(
'MESSAGE_URI_TEMPLATE', 'https://chat.example.com/messages/{id}')
SUBSCRIPTIONS_TEMPLATE = '/.well-known/mercure/subscriptions/{topic}{/subscriber}'
SUBSCRIPTIONS_TOPIC = expand(SUBSCRIPTIONS_TEMPLATE, topic=MESSAGE_URI_TEMPLATE)
app = Flask(__name__)
@app.route('/', methods=['GET'])
def join():
return render_template('join.html')
@app.route('/', methods=['POST'])
def chat():
username = request.form['username']
if not username:
abort(400)
token = jwt.encode(
{'mercure':
{
'subscribe': [MESSAGE_URI_TEMPLATE, SUBSCRIPTIONS_TEMPLATE],
'publish': [MESSAGE_URI_TEMPLATE],
'payload': {'username': username}
}
},
JWT_KEY,
algorithm='HS256',
)
resp = make_response(render_template('chat.html', config={
'hubURL': HUB_URL, 'messageURITemplate': MESSAGE_URI_TEMPLATE, 'subscriptionsTopic': SUBSCRIPTIONS_TOPIC, 'username': username}))
resp.set_cookie('mercureAuthorization', token, httponly=True, path='/.well-known/mercure',
samesite="strict", domain=os.environ.get('COOKIE_DOMAIN', None), secure=request.is_secure) # Force secure to True for real apps
return resp