我的 ASGI 应用程序可以很好地向 curl 和我的手机发送事件。但是,即使服务器正在发送事件,并且标头看起来正确,但我的 Windows 机器上的 Firefox 和 Chrome 都不会收到事件,直到连接关闭。
无论我将服务器托管在 WSL、Powershell 终端还是单独的 Linux 机器上,都会发生这种情况。
但是,如果我在 repl.it 上托管服务器,这些相同的浏览器可以正常工作(请分叉并试用)。
我曾尝试摆弄 Windows 防火墙设置,但无济于事。
这是应用程序代码:
import asyncio
import datetime
async def app(scope, receive, send):
headers = [(b"content-type", b"text/html")]
if scope["path"] == "/":
body = (
"<html>"
"<body>"
"</body>"
"<script>"
" let eventSource = new EventSource('/sse');"
" eventSource.addEventListener('message', (e) => {"
" document.body.innerHTML += e.data + '<br>';"
" });"
"</script>"
"</html>"
).encode()
await send({"type": "http.response.start", "status": 200, "headers": headers})
await send({"type": "http.response.body", "body": body})
elif scope["path"] == "/sse":
headers = [
(b"content-type", b"text/event-stream"),
(b"cache-control", b"no-cache"),
(b"connection", b"keep-alive"),
]
async def body():
ongoing = True
while ongoing:
try:
payload = datetime.datetime.now()
yield f"data: {payload}\n\n".encode()
await asyncio.sleep(10)
except asyncio.CancelledError:
ongoing = False
await send({"type": "http.response.start", "status": 200, "headers": headers})
async for chunk in body():
await send({"type": "http.response.body", "body": chunk, "more_body": True})
await send({"type": "http.response.body", "body": b""})
else:
await send({"type": "http.response.start", "status": 404, "headers": headers})
await send({"type": "http.response.body", "body": b""})
这可以通过将上面的文件命名为asgi_sse.py
, 然后pip install uvicorn
, 然后使用类似的东西来运行
uvicorn asgi_sse:app
(替换daphne
或hypercorn
代替uvicorn
上面的内容,看看这些服务器如何处理应用程序。)
标题:
$ curl -I http://localhost:8000/sse
HTTP/1.1 200 OK
date: Mon, 01 Jun 2020 09:51:41 GMT
server: uvicorn
content-type: text/event-stream
cache-control: no-cache
connection: keep-alive
和回应:
$ curl http://localhost:8000/sse
data: 2020-06-01 05:52:40.735403
data: 2020-06-01 05:52:50.736378
data: 2020-06-01 05:53:00.736812
任何见解都非常受欢迎!