为什么我的生成器阻止Flask发送SSE响应? [英] Why does my generator block Flask from sending SSE responses?

查看:177
本文介绍了为什么我的生成器阻止Flask发送SSE响应?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



在这里,我的客户端只接收事件,我的生成器函数已经停止/连接关闭。是我已经能够证明这一点的最简单的再现:

 #!/ usr / bin / env python 

从烧瓶导入烧瓶,响应
从时间导入sleep

def stream():
n = 10
while n> 0:
yielddata:hi \\\
\\\

sleep(0.5)
n = n - 1

app = Flask(__ name__)

@ app.route(/ events)
def streamSessionEvents():
返回响应(
stream(),
mimetype =text / event -stream


app.run(debug = True,threaded = True)

以下是我的测试客户端:

 <!doctype html> 
< html>
< head>
< script>
var source = new EventSource(
/ events
);
source.onmessage = function(event)
{
console.log(event);
};
< / script>
< / head>
< body>
< / body>
< / html> ()生成器将产生10个事件,然后返回(我已经故意做了这个演示这个问题,理想情况下,发电机将永远持续下去),在这一点上连接被丢弃。客户端页面没有记录任何东西,直到这一点,然后它吐出所有十个事件(如果我没有在流()的计数器变量,那么该网页从来没有得到任何事件)。

<我没有使用Python或Flask很多,这让我非常困惑,我不能看到我在网上的其他例子有什么不同。任何帮助非常感谢。

解决方案




  1. 您将 debug 设置为 True ,安装中间件 Werkzeug调试器)可能会破坏流式传输。



    来自 Flask streaming patterns文件


    请注意,有些WSGI中间件可能会中断流式传输,因此在调试环境中请注意配置文件和其他您可能已启用的功能。


    但是,在Flask 0.10.1和Werkzeug 0.9.4的测试代码中使用 curl 或Chrome,无论 debug 标记设置如何, data:hi 响应都能正确流入。换句话说,您的代码可以正常使用Flask堆栈的最新版本。

  2. /en.wikipedia.org/wiki/Same-origin_policyrel =nofollow>同源政策限制。如果您没有从相同的主机和端口加载HTML页面,则拒绝向您的Flask服务器发送请求。



    在Flask服务器中添加测试页面源代码一个单独的路线适用于我:

      @ app.route('/')
    def index():
    return'''\
    <!doctype html>
    < html>
    < head>
    < script>
    var source = new EventSource(
    / events
    );
    source.onmessage = function(event)
    {
    console.log(event);
    };
    < / script>
    < / head>
    < body>
    < / body>
    < / html>
    '''



I am trying to use Flask to serve an SSE request, but my client only receives the events after my generator function has stopped / the connection is closed.

Here is the simplest reproduction I have been able to produce to demonstrate this:

#!/usr/bin/env python

from flask import Flask, Response
from time import sleep

def stream():
    n = 10
    while n > 0:
        yield "data: hi\n\n"
        sleep(0.5)
        n = n - 1

app = Flask(__name__)

@app.route("/events")
def streamSessionEvents():
    return Response(
        stream(),
        mimetype="text/event-stream"
    )

app.run(debug=True, threaded=True)

Here is my test client:

<!doctype html>
<html>
<head>
    <script>
        var source = new EventSource(
            "/events"
        );
        source.onmessage = function(event)
        {
            console.log(event);
        };
    </script>
</head>
<body>
</body>
</html>

The stream() generator will produce ten events and then return (I've deliberately done this to demonstrate the problem, ideally the generator would keep going forever), at which point the connection is dropped. The client page logs nothing until this point, then it spits out all ten events (if I dont have the counter variable in stream() then the page never gets any events).

I havent used Python or Flask a great deal and this has me very stuck, I cant see what I'm doing differently to other examples around the net. Any help very much appreciated.

解决方案

Two things might interfere:

  1. You have debug set to True, which installs middleware (specifically the Werkzeug debugger) that may break streaming.

    From the Flask streaming patterns documentation:

    Note though that some WSGI middlewares might break streaming, so be careful there in debug environments with profilers and other things you might have enabled.

    However, using either curl or Chrome on your test code with Flask 0.10.1 and Werkzeug 0.9.4 I see the data: hi responses come streaming through properly, regardless of the debug flag setting. In other words, your code is working correctly with the most recent versions of the Flask stack.

  2. EventSource streams are subject to same-origin policy limits. If you are not loading the HTML page from the same host and port, the request to your Flask server will be denied.

    Adding the test page source in the Flask server at a separate route works for me:

    @app.route('/')
    def index():
        return '''\
    <!doctype html>
    <html>
    <head>
        <script>
            var source = new EventSource(
                "/events"
            );
            source.onmessage = function(event)
            {
                console.log(event);
            };
        </script>
    </head>
    <body>
    </body>
    </html>
    '''
    

这篇关于为什么我的生成器阻止Flask发送SSE响应?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆