Domanda

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.

È stato utile?

Soluzione

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>
    '''
    
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top