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でどうぞ。


この記事が気に入ったらサポートをしてみませんか?