I'm trying to build real time notification system for users using Server sent events in python.
The issue I'm facing is when I refresh the browser, which means the browser then will try to hit the EventSource url again, and as per docs it should send the event.lastEventId as part of headers in next request. I'm getting None every time I refresh the page.
<!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>
On the server side
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
Now, as per every doc on SSE, when client reconnects or refreshes the page it will send the last-event-id in headers. I'm trying to read it using request.headers.get('last-event-id'), but this is always null.
Any pointers on how to get the last event id would be helpful. Also, how would I make sure that I do't send the same events even later once the user has seen the events, as my entire logic would be based on last-event-id received by the server, so if its None after reading events with Id 1 to 4, how would I make sure in server that I should not send these back even if last-event-id is null for the user
.
Adding browser snaps
1st pic shows that the events are getting received by the browser. e.g. {alpha: abc, id:4}
2nd pic shows that the event received is setting the lastEventId correctly.