68 lines
1.9 KiB
Python
68 lines
1.9 KiB
Python
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
|
|
|