How do I close a Server-Send Events connection in Flask?

淺唱寂寞╮ 提交于 2020-01-01 02:50:06

问题


The below has given an answer using node.js.

How to close a "Server-Sent Events"-connection on the server?

However, how to do the same thing in python Flask?


回答1:


Well, it depends on the architecture of your app.

Let me show you an example (see this code at https://github.com/jkbr/chat/blob/master/app.py):

def event_stream():
    pubsub = red.pubsub()
    pubsub.subscribe('chat')
    for message in pubsub.listen():
        print message
        yield 'data: %s\n\n' % message['data']

@app.route('/stream')
def stream():
    return flask.Response(event_stream(),
                          mimetype="text/event-stream")

Flask asks a new message to Redis (locking operation) steadily, but when Flask sees that streaming terminates (StopIteration, if you aren't new to Python), it returns.

def event_stream():
    pubsub = red.pubsub()
    pubsub.subscribe('chat')
    for message in pubsub.listen():
        if i_should_close_the_connection:
            break
        yield 'data: %s\n\n' % message['data']

@app.route('/stream')
def stream():
    return flask.Response(event_stream(),
                          mimetype="text/event-stream")



回答2:


I had the same problem and finally found the following solution here.

import time
from flask import Flask, Response, stream_with_context

app = Flask(__name__)

@app.route('/stream')
def stream():
    def gen():
        try:
            i = 0
            while True:
                data = 'this is line {}'.format(i)
                print(data)
                yield data + '<br>'
                i += 1
                time.sleep(1)
        except GeneratorExit:
            print('closed')

    return Response(stream_with_context(gen()))

You can start the method with subscribing a listener to Redis. Instead of time.sleep(1) you could wait for Redis' listen() method to return a vlaue. Instead of print('closed') you could unsubscribe from Redis. The only problem left is that the GeneratorExit exception is only raised when the yield value is being sent to the client. So if Redis' listen() never ends, then you will never discover that the connection has been broken.



来源:https://stackoverflow.com/questions/11597367/how-do-i-close-a-server-send-events-connection-in-flask

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!