PythonとWebフレームワークとServer Sent Events
Pythonはサーバーを立てるのがすごく簡単です。
python -m http.server 8080
だけでWebサーバが立ち上がってくれるんです! XAMPPの存在を知った時も結構感動しましたが、pythonのこの手軽さはその比ではありません。
ちょっとした処理を返すサーバがほしい時も、フレームワークを使ってチョチョイノチョイで出来上がります。
from bottle import run, route
@route('/')
def index():
return "hello world!"
run(host="localhost", port=8080, debug=True, reloader=True)
さて、仕事でServer Sent Eventsなるものを利用する機会がありました。
普通のWebの通信は、クライアント側から「何か情報おくれ」と催促することではじめてサーバが応答を返す仕組みですが、SSEはサーバ側から「情報だよ!」とクライアントに押し付ける通信なのです。
もう少し詳しく書いてみましょう。
SSEはクライアントとサーバの通信を永続的に維持し、その過程でサーバからクライアントに情報を垂れ流す仕組みなのです。SSEではクライアントからサーバに情報を送信するのは最初だけなので、途中でクライアントからサーバに何かしらの送信を行う時は、別途ajaxなりを利用します。
このSSEを使ってクライアントでどーのこーのする処理をJavascriptで書いたのですが、そのテストを行うための環境をPythonで整えてみることにしました。
from bottle import response
import time
@route('/sse')
def sse():
response.headers['Access-Control-Allow-Origin'] = '*'
response.headers['Content_Type'] = 'text/event-stream'
while (True):
yield 'data:"hello SSE"\n\n'
time.sleep(1)
このコードのキモは3つあります。
ひとつはContent_Typeの"text/event-stream"で、SSEの通信をするというおまじないです。
次にwhile文。先に「永続的に維持し」と書きましたが、その永続を維持するのがこのwhileです。このwhileを書かないとその都度関数が終了し、クライアントからは原因不明のセッション断と判断されてエラーが出まくります。
そして最後が、yieldとそこで返す文字列の末尾の"\n\n"です。クライアントから見ると、サーバからデータが垂れ流され続けてくるので、どこからどこまでがひとまとまりなのか分かりません。そこで改行コードを2つ重ね、データの区切りとしているのです。
yieldは呼び出し先に結果を返しつつも、関数を終了させないというシロモノです。returnだとsse関数から抜けちゃうんで「永続」が維持されません。
ミニマムな実装はgithubでどうぞ。