jdb*_*w75 3 python antivirus server-sent-events python-asyncio asgi
我的 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""})
Run Code Online (Sandbox Code Playgroud)
可以通过将上面的文件命名为asgi_sse.py,然后pip install uvicorn,然后使用类似的命令来运行
uvicorn asgi_sse:app
Run Code Online (Sandbox Code Playgroud)
(用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
Run Code Online (Sandbox Code Playgroud)
以及回应:
$ 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
Run Code Online (Sandbox Code Playgroud)
任何见解都非常受欢迎!
我最近遇到了同样的问题,但使用的是 NodeJS + Express 应用程序。如果连接不安全,我最终会发送 2 MB 的块。
if (!req.secure) {
res.write(new Array(1024 * 1024).fill(0).toString());
}
Run Code Online (Sandbox Code Playgroud)
这是为了让服务器发送的事件在没有安全连接的开发环境中工作。
完整的实现:
app.use('/stream', (req, res) => {
res.set({
'Content-Type': 'text/event-stream;charset=utf-8',
'Cache-Control': 'no-cache, no-transform',
'Content-Encoding': 'none',
'Connection': 'keep-alive'
});
res.flushHeaders();
if (!req.secure) {
res.write(new Array(1024 * 1024).fill(0).toString());
}
const sendEvent = (event, data) => {
res.write(`event: ${String(event)}\n`);
res.write(`data: ${data}`);
res.write('\n\n');
res.flushHeaders();
};
const intervalId = setInterval(() => {
sendEvent('ping', new Date().toLocaleTimeString());
}, 5000);
req.on('close', () => {
clearInterval(intervalId);
});
});
Run Code Online (Sandbox Code Playgroud)