Браузер refre sh не отправляет последний идентификатор события, полученный как часть ответа сервера, отправленного - PullRequest
0 голосов
/ 28 апреля 2020

Я пытаюсь создать систему уведомлений в реальном времени для пользователей, использующих события, отправленные сервером, в python.

Проблема, с которой я сталкиваюсь, связана с обновлением sh браузера, который означает, что браузер затем попытается снова обратиться к URL-адресу EventSource, и в соответствии с документацией он должен отправить event.lastEventId как часть заголовков в следующем запросе. Я получаю None каждый раз, когда я обновляю sh страницу.

<!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

Теперь, как за каждый do c в SSE, когда клиент повторно подключается или обновляет страницу, он отправляет идентификатор последнего события в заголовках. Я пытаюсь прочитать его с помощью request.headers.get ('last-event-id'), но это всегда значение null.

Любые указатели на то, как получить последний идентификатор события, были бы полезны. Кроме того, как мне убедиться, что я не отправляю те же события даже позже, когда пользователь увидит эти события, так как все мои логи c будут основаны на последнем идентификаторе события, полученном сервером, так что если его Ни один после чтения событий с Id с 1 по 4, как бы я убедился на сервере, что я не должен отправлять их обратно, даже если last-event-id является нулевым для пользователя

.

Добавление снимков браузера

1st pi c показывает, что события принимаются браузером. например, {alpha: ab c, id: 4}

2nd pi c показывает, что полученное событие правильно устанавливает lastEventId.

enter image description here

enter image description here

...