Have EventManagers yield before timer code to force SSE response head… (#1400)

* EventManagers should send an initial ping event to force `text/event-steam` header to be set
This commit is contained in:
Kevin Chung
2020-05-13 19:33:01 -04:00
committed by GitHub
parent 1a57a33fe7
commit 2769dc6367
2 changed files with 31 additions and 10 deletions

View File

@@ -52,6 +52,10 @@ class EventManager(object):
self.clients.append(q)
while True:
try:
# Immediately yield a ping event to force Response headers to be set
# or else some reverse proxies will incorrectly buffer SSE
yield ServerSentEvent(data="", type="ping")
with Timeout(10):
message = q[channel].get()
yield ServerSentEvent(**message)
@@ -76,6 +80,10 @@ class RedisEventManager(EventManager):
pubsub = self.client.pubsub()
pubsub.subscribe(channel)
try:
# Immediately yield a ping event to force Response headers to be set
# or else some reverse proxies will incorrectly buffer SSE
yield ServerSentEvent(data="", type="ping")
with Timeout(10) as timeout:
for message in pubsub.listen():
if message["type"] == "message":

View File

@@ -35,11 +35,18 @@ def test_event_manager_subscription():
fake_queue.return_value = saved_event
event_manager = EventManager()
for message in event_manager.subscribe():
assert message.to_dict() == saved_event
assert message.__str__().startswith("event:notification\ndata:")
assert len(event_manager.clients) == 1
break
events = event_manager.subscribe()
message = next(events)
assert isinstance(message, ServerSentEvent)
assert message.to_dict() == {"data": "", "type": "ping"}
assert message.__str__().startswith("event:ping")
assert len(event_manager.clients) == 1
message = next(events)
assert isinstance(message, ServerSentEvent)
assert message.to_dict() == saved_event
assert message.__str__().startswith("event:notification\ndata:")
assert len(event_manager.clients) == 1
def test_event_manager_publish():
@@ -144,11 +151,17 @@ def test_redis_event_manager_subscription():
with patch.object(redis.client.PubSub, "listen") as fake_pubsub_listen:
fake_pubsub_listen.return_value = [saved_event]
event_manager = RedisEventManager()
for message in event_manager.subscribe():
assert isinstance(message, ServerSentEvent)
assert message.to_dict() == saved_data
assert message.__str__().startswith("event:notification\ndata:")
break
events = event_manager.subscribe()
message = next(events)
assert isinstance(message, ServerSentEvent)
assert message.to_dict() == {"data": "", "type": "ping"}
assert message.__str__().startswith("event:ping")
message = next(events)
assert isinstance(message, ServerSentEvent)
assert message.to_dict() == saved_data
assert message.__str__().startswith("event:notification\ndata:")
destroy_ctfd(app)