SSE - Server-Sent-Events
介绍
- EventStream(事件流)为UTF-8格式编码的文本或以Base64编码和gzip压缩的二进制消息;
- 每条消息由一行或多行字段组成,每个字段组成形式为:
字段名:字段值
,字段以行为单位(既以\n结尾); - 以:开头的行为注释行会被浏览器忽略;
- 每次推送,可由多个消息组成,每个消息之间以空行为分隔(既最后一个字段以\n\n结尾)
消息字段
- data: 数据
- event: 事件类型 【可选】
- id: 消息ID【可选】
- retry: 重连间隔时间【可选】
特点
- 通信方式,单向通信,只能由服务端向客户端发送数据;
- 协议,基于HTTP协议;
- 数据格式,数据格式固定,必须是
text/event-stream
; - 连接,SSE在断开后可自动重连;
- 浏览器支持,在某些旧版浏览器中不被支持,如IE。
服务端
# fastapi 实现
@router.get('/stream', summary='stream')
async def stream():
headers = {
'Content-Type': 'text/event-stream; charset=utf-8',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive'
}
def generate_data() -> Generator[str, None, None]:
for i in range(10):
data = {'index': i, 'message': f'Data chunk {i}'}
yield f'data: {data}\n\n'.encode('utf-8')
time.sleep(1)
return StreamingResponse(generate_data(), media_type='text/event-stream', headers=headers)
客户端
// javascript 实现
const eventSource = new EventSource("http://localhost:8090/api/test/stream");
eventSource.onopen = function () {
console.log("连接")
};
eventSource.onmessage = function(event: any) {
console.log(event.data)
};
eventSource.onerror = function(error: any) {
console.error(error)
eventSource.close()
};
# python 实现
import requests
response = requests.get('http://localhost:8090/api/test/stream', stream=True)
if response.status_code == 200:
for line in response.iter_lines():
if line:
data = line.decode('utf-8')
print(data)
else:
print('Failed to get data. Status code: {response.status_code}')