我正在尝试为使用 python 中的服务器发送事件的用户构建实时通知系统。
我面临的问题是当我刷新浏览器时,这意味着浏览器将尝试再次点击 EventSource url,并且根据文档,它应该在下一个请求中将 event.lastEventId 作为标头的一部分发送。每次刷新页面时我都会得到无。
<!DOCTYPE html>
<html>
<header><title>SSE test</title></header>
<body>
<ul id="list"></ul>
<script>
const evtSource = new EventSource("/streams/events?token=abc");
evtSource.onmessage = function(event) {
console.log('event', event)
console.log('event.lastEventId', event.lastEventId)
const newElement = document.createElement("li");
const eventList = document.getElementById("list");
newElement.innerHTML = "message: " + event.data;
eventList.appendChild(newElement);
}
</script>
</body>
</html>
在服务器端
from sse_starlette.sse import EventSourceResponse
from asyncio.queues import Queue
from starlette.requests import Request
@event_router.get(
"/streams/events",
status_code=HTTP_200_OK,
summary='',
description='',
response_description='')
async def event_stream(request: Request):
return EventSourceResponse(send_events(request))
async def send_events(request: Request):
try:
key = request.query_params.get('token')
last_id = request.headers.get('last-event-id')
print('last_id ', last_id) # this value is always None
connection = Queue()
connections[key] = connection
while RUNNING:
next_event = await connection.get()
print('event', next_event)
yield dict(data=next_event, id=next_event['id'])
connection.task_done()
except asyncio.CancelledError as error:
pass
现在,根据 SSE 上的每个文档,当客户端重新连接或刷新页面时,它将在标题中发送 last-event-id。我正在尝试使用 request.headers.get('last-event-id') 读取它,但这始终为空。
有关如何获取最后一个事件 ID 的任何指示都会有所帮助。另外,一旦用户看到事件,我将如何确保即使稍后我也不会发送相同的事件,因为我的整个逻辑将基于服务器接收到的 last-event-id,所以如果它在阅读后为 None Id 1 到 4 的事件,我如何确保在服务器中我不应该将这些发回,即使用户的 last-event-id 为空
.
添加浏览器快照
第一张图片显示浏览器正在接收事件。例如 {alpha: abc, id:4}
第二张图片显示收到的事件正确设置了 lastEventId。