https://github.com/zeekay/flask-uwsgi-websocket/tree/master/examples/chat-gevent
https://github.com/GoogleCloudPlatform/python-docs-samples/tree/master/appengine/flexible/websockets
から書き直してみた。
ファイルツリー
chat/
├ static/
| js/
| └ main.js
├ templates/
| └ index.html
├ chat.py
└ requirements.txt
ファイル
main.js
(function () {
function showMessage(message) {
$('#messages').append('<li>' + message)
}
if (!window.WebSocket) {
if (window.MozWebSocket) {
window.WebSocket = window.MozWebSocket;
} else {
showMessage("Your browser doesn't support WebSockets")
}
}
let scheme = window.location.protocol === "https:" ? 'wss://' : 'ws://';
let webSocketUri = scheme
+ window.location.hostname
+ (location.port ? ':' + location.port : '')
+ $SCRIPT_ROOT + '/websocket';
let ws = new WebSocket(webSocketUri);
ws.onopen = function (evt) {
showMessage('Connected to chat.')
}
ws.onmessage = function (evt) {
showMessage(evt.data)
}
ws.onclose = function (evt) {
$('#messages').append('<li>WebSocket connection closed.</li>');
}
$('#send-message').on("submit", function () {
let message = $('#name').val() + ": " + $('#message').val();
showMessage(message)
ws.send(message);
$('#message').val('').trigger('focus');
return false;
});
}());
index.html
<!doctype html>
<head>
<meta charset="utf-8"/>
<title>WebSocket Chat Example</title>
<style>
li {
list-style: none;
}
</style>
<script type=text/javascript>
$SCRIPT_ROOT =
{{ request.script_root|tojson|safe }}
</script>
</head>
<body>
<h2>WebSocket Chat Example</h2>
<form id="send-message">
<input id="name" type="text" value="name">
<input id="message" type="text" value="message"/>
<input type="submit" value="Send"/>
</form>
<div id="messages"></div>
</body>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
crossorigin="anonymous"></script>
<script src="{{ url_for('static', filename='js/main.js') }}"></script>
</html>
chat.py
import os
from collections import deque
from flask import Flask, render_template, url_for
from flask_uwsgi_websocket import GeventWebSocket
app = Flask(__name__)
ws = GeventWebSocket(app)
users = {}
backlog = deque(maxlen=10)
@app.context_processor
def override_url_for():
return dict(url_for=dated_url_for)
def dated_url_for(endpoint, **values):
if endpoint == 'static':
filename = values.get('filename', None)
if filename:
file_path = os.path.join(app.root_path,
endpoint, filename)
values['q'] = int(os.stat(file_path).st_mtime)
return url_for(endpoint, **values)
@app.route('/')
def index():
return render_template('index.html')
@ws.route('/websocket')
def chat(ws):
users[ws.id] = ws
for msg in backlog:
ws.send(msg)
while True:
msg = ws.receive()
if msg is None:
break
if msg == b"":
continue
backlog.append(msg)
for id in users:
if id != ws.id:
users[id].send(msg)
del users[ws.id]
return
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0', port=8080, gevent=100)
requirements.txt
click==7.1.2
Flask==1.1.2
Flask-uWSGI-WebSocket==0.6.1
gevent==20.6.2
greenlet==0.4.16
itsdangerous==1.1.0
Jinja2==2.11.2
MarkupSafe==1.1.1
uWSGI==2.0.19.1
Werkzeug==1.0.1
zope.event==4.4
zope.interface==5.1.0
インストール
$ python3 -m venv venv
$ source venv/bin/activate
$ pip install requirements.txt
実行
$ python chat.py