Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement server push in Flask framework?

I am trying to build a small site with the server push functionality on Flask micro-web framework, but I did not know if there is a framework to work with directly.

I used Juggernaut, but it seems to be not working with redis-py in current version, and Juggernaut has been deprecated recently.

Does anyone has a suggestion with my case?

like image 658
little-eyes Avatar asked Sep 01 '12 23:09

little-eyes


People also ask

How do I deploy Flask app to remote server?

If you want the Flask app to run on a remote system, you must install it and run it on that system. If you are the system administrator, that means copying the application (and its dependencies) over and setting up a WSGI web server to run it on the server.

How do you deploy a Flask on a Windows server?

Inside FlaskApp folder, create the Flask Application file “app.py”. Now, copy the “wfastcgi.py” file from “C:\Python\Lib\site-packages\” directory and paste it to “C:\inetpub\wwwroot\FlaskApp\” directory. Now, as the permissions are added, we are ready to deploy our Flask application in the IIS server.

Does Flask use threads or processes?

As of Flask 1.0, flask server is multi-threaded by default. Each new request is handled in a new thread. This is a simple Flask application using default settings.


2 Answers

Have a look at Server-Sent Events. Server-Sent Events is a browser API that lets you keep open a socket to your server, subscribing to a stream of updates. For more Information read Alex MacCaw (Author of Juggernaut) post on why he kills juggernaut and why the simpler Server-Sent Events are in manny cases the better tool for the job than Websockets.

The protocol is really easy. Just add the mimetype text/event-stream to your response. The browser will keep the connection open and listen for updates. An Event sent from the server is a line of text starting with data: and a following newline.

data: this is a simple message <blank line> 

If you want to exchange structured data, just dump your data as json and send the json over the wire.

An advantage is that you can use SSE in Flask without the need for an extra Server. There is a simple chat application example on github which uses redis as a pub/sub backend.

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('/post', methods=['POST']) def post():     message = flask.request.form['message']     user = flask.session.get('user', 'anonymous')     now = datetime.datetime.now().replace(microsecond=0).time()     red.publish('chat', u'[%s] %s: %s' % (now.isoformat(), user, message))   @app.route('/stream') def stream():     return flask.Response(event_stream(),                           mimetype="text/event-stream") 

You do not need to use gunicron to run the example app. Just make sure to use threading when running the app, because otherwise the SSE connection will block your development server:

if __name__ == '__main__':     app.debug = True     app.run(threaded=True) 

On the client side you just need a Javascript handler function which will be called when a new message is pushed from the server.

var source = new EventSource('/stream'); source.onmessage = function (event) {      alert(event.data); }; 

Server-Sent Events are supported by recent Firefox, Chrome and Safari browsers. Internet Explorer does not yet support Server-Sent Events, but is expected to support them in Version 10. There are two recommended Polyfills to support older browsers

  • EventSource.js
  • jquery.eventsource
like image 113
Peter Hoffmann Avatar answered Sep 22 '22 04:09

Peter Hoffmann


Redis is overkill: use Server-Sent Events (SSE)

Late to the party (as usual), but IMHO using Redis may be overkill.

As long as you're working in Python+Flask, consider using generator functions as described in this excellent article by Panisuan Joe Chasinga. The gist of it is:

In your client index.html

var targetContainer = document.getElementById("target_div"); var eventSource = new EventSource("/stream")   eventSource.onmessage = function(e) {   targetContainer.innerHTML = e.data; }; ... <div id="target_div">Watch this space...</div> 

In your Flask server:

def get_message():     '''this could be any function that blocks until data is ready'''     time.sleep(1.0)     s = time.ctime(time.time())     return s  @app.route('/') def root():     return render_template('index.html')  @app.route('/stream') def stream():     def eventStream():         while True:             # wait for source data to be available, then push it             yield 'data: {}\n\n'.format(get_message())     return Response(eventStream(), mimetype="text/event-stream") 
like image 39
fearless_fool Avatar answered Sep 24 '22 04:09

fearless_fool