import queue from collections import namedtuple from . import httpd PendingEvent = namedtuple('PendingEvent', ['data', 'name', 'id']) class ServerSideEvents(httpd.Handler): """ Base class for server side events. See the specification of the W3C at http://dev.w3.org/html5/eventsource/ This class handles decoupling through the default Queue. Events can be posted for transmission by using send_event. """ def __init__(self, request): super().__init__(request) self.queue = queue.Queue() def send_event(self, data, name=None, id=None): self.queue.put(PendingEvent(data, name, id)) def go_subscribe(self): pass def go_unsubscribe(self): pass def handle_GET(self): self.go_subscribe() # Send HTTP headers: self.request.send_response(200) self.request.send_header("Content-type", "text/event-stream") self.request.end_headers() done = False while not done: event = self.queue.get() if event == None: done = True else: done = not self._send_message(event) self.go_unsubscribe() def _send_message(self, event): try: if event.id is not None: id_line = "id: {}\n".format(event.id) self.request.wfile.write(id_line.encode('utf-8')) if event.name is not None: event_line = "event: {}\n".format(event.name) self.request.wfile.write(event_line.encode('utf-8')) data_line = "data: {}\n".format(event.data) self.request.wfile.write(data_line.encode('utf-8')) self.request.wfile.write("\n".encode('utf-8')) self.request.wfile.flush() return True except IOError: return False