服务器发送事件#
Quart 支持流式 服务器发送事件,您可以选择将其用作 WebSocket 的替代方案 - 特别是当通信为单向时。
服务器发送事件必须以特定方式编码,如以下辅助类所示
from dataclasses import dataclass
@dataclass
class ServerSentEvent:
data: str
event: str | None = None
id: int | None = None
retry: int | None
def encode(self) -> bytes:
message = f"data: {self.data}"
if self.event is not None:
message = f"{message}\nevent: {self.event}"
if self.id is not None:
message = f"{message}\nid: {self.id}"
if self.retry is not None:
message = f"{message}\nretry: {self.retry}"
message = f"{message}\n\n"
return message.encode('utf-8')
要使用返回流式生成器的 GET 路由,需要一个这样的生成器。此生成器 (在以下代码中为 send_events
) 必须生成编码的服务器发送事件。该路由本身还需要检查客户端是否接受 text/event-stream
响应并相应地设置响应头
from quart import abort, make_response
@app.get("/sse")
async def sse():
if "text/event-stream" not in request.accept_mimetypes:
abort(400)
async def send_events():
while True:
data = ... # Up to you where the events are from
event = ServerSentEvent(data)
yield event.encode()
response = await make_response(
send_events(),
{
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Transfer-Encoding': 'chunked',
},
)
response.timeout = None
return response
Quart 默认情况下会超时长响应,以防止可能的拒绝服务攻击,请参阅 拒绝服务缓解措施。因此,超时被禁用。这可以在全局范围内完成,但是这可能会使其他路由容易受到 DOS 攻击,因此建议将超时属性设置为特定响应的 None
。