mirror of
https://github.com/aljazceru/CTFd.git
synced 2025-12-18 14:34:21 +01:00
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:
@@ -52,6 +52,10 @@ class EventManager(object):
|
|||||||
self.clients.append(q)
|
self.clients.append(q)
|
||||||
while True:
|
while True:
|
||||||
try:
|
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):
|
with Timeout(10):
|
||||||
message = q[channel].get()
|
message = q[channel].get()
|
||||||
yield ServerSentEvent(**message)
|
yield ServerSentEvent(**message)
|
||||||
@@ -76,6 +80,10 @@ class RedisEventManager(EventManager):
|
|||||||
pubsub = self.client.pubsub()
|
pubsub = self.client.pubsub()
|
||||||
pubsub.subscribe(channel)
|
pubsub.subscribe(channel)
|
||||||
try:
|
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:
|
with Timeout(10) as timeout:
|
||||||
for message in pubsub.listen():
|
for message in pubsub.listen():
|
||||||
if message["type"] == "message":
|
if message["type"] == "message":
|
||||||
|
|||||||
@@ -35,11 +35,18 @@ def test_event_manager_subscription():
|
|||||||
|
|
||||||
fake_queue.return_value = saved_event
|
fake_queue.return_value = saved_event
|
||||||
event_manager = EventManager()
|
event_manager = EventManager()
|
||||||
for message in event_manager.subscribe():
|
events = event_manager.subscribe()
|
||||||
assert message.to_dict() == saved_event
|
message = next(events)
|
||||||
assert message.__str__().startswith("event:notification\ndata:")
|
assert isinstance(message, ServerSentEvent)
|
||||||
assert len(event_manager.clients) == 1
|
assert message.to_dict() == {"data": "", "type": "ping"}
|
||||||
break
|
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():
|
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:
|
with patch.object(redis.client.PubSub, "listen") as fake_pubsub_listen:
|
||||||
fake_pubsub_listen.return_value = [saved_event]
|
fake_pubsub_listen.return_value = [saved_event]
|
||||||
event_manager = RedisEventManager()
|
event_manager = RedisEventManager()
|
||||||
for message in event_manager.subscribe():
|
|
||||||
assert isinstance(message, ServerSentEvent)
|
events = event_manager.subscribe()
|
||||||
assert message.to_dict() == saved_data
|
message = next(events)
|
||||||
assert message.__str__().startswith("event:notification\ndata:")
|
assert isinstance(message, ServerSentEvent)
|
||||||
break
|
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)
|
destroy_ctfd(app)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user