Fixed flag server socket event

I am going to use SSE to input new data to the client and use the Flot (javascript charting library) to display live updates. My server runs on the python framework and I figured out how to push data to the client, but the problem arises as soon as I leave the page:

Exception happened during processing of request from ('127.0.0.1', 38814)
Traceback (most recent call last):
  File "/usr/lib/python2.7/SocketServer.py", line 582, in process_request_thread
    self.finish_request(request, client_address)
  File "/usr/lib/python2.7/SocketServer.py", line 323, in finish_request
    self.RequestHandlerClass(request, client_address, self)
  File "/usr/lib/python2.7/SocketServer.py", line 640, in __init__
    self.finish()
  File "/usr/lib/python2.7/SocketServer.py", line 693, in finish
    self.wfile.flush()
  File "/usr/lib/python2.7/socket.py", line 303, in flush
    self._sock.sendall(view[write_offset:write_offset+buffer_size])
error: [Errno 32] Broken pipe

I understand why an error occurs - a socket never closes due to an infinite loop serving live data. The question is, how do I detect a page change and a clean socket close? Can I close the connection on the client side? How to detect a page change?

This is the skeleton of the server code, I would of course replace the text message with json containing a list of displayed objects:

def event_stream():
    import time
    while True:
        time.sleep(1)
        yield "data: This is a message number X.\n\n"

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

onBeforeUnload, jQuery window.unload(), Ajax , . - :

$(window).unload(
    function() {
        $.ajax(type: 'POST',
               async: false,
               url: 'foo.com/client_teardown')
    }
}

, unload()/onBeforeUnload(), , Chrome.

+1

, , ajax .

SSE Response, disconnect pipe Response, .

+2

( mokey), .

SocketServer.StreamRequestHandler.finish exception, , , ,

import socket
import SocketServer

def patched_finish(self):
    try:
        if not self.wfile.closed:
            self.wfile.flush()
            self.wfile.close()
    except socket.error:
        # Remove this code, if you don't need access to the Request object
        if _request_ctx_stack.top is not None:
            request = _request_ctx_stack.top.request
            # More cleanup code...
    self.rfile.close()

SocketServer.StreamRequestHandler.finish = patched_finish

Request, flask.stream_with_context, :

@app.route(url)
def method(host):
    return Response(stream_with_context(event_stream()),
                    mimetype='text/event-stream')

, , , , WSGI.

+1

Flask dev wsgi prod env. uwsgi, .

python3, , .

0

All Articles