一、背景原因
近期在做一个可视化项目,需要后端提供实时的数据。经过对比选择了SSE(服务器推送事件)的方案,需要先通过JWT认证,给EventSource设置了请求头但不起作用。原始代码如下:
async initDashboard(){
this.sse = new EventSource(this.baseUrl + '/dashboard', {
withCredentials: true,
headers: {
'Authorization': `Bearer ${getToken()}`
},
});
this.sse.onmessage = (event) => {
try {
if (event.data && typeof event.data === 'string') {
const res = JSON.parse(event.data);
const { visit = [], comment, union, product = [], network } = res.data;
// 处理数据方法
// ...
}
} catch (err) {
console.log('SEE初始化异常', JSON.stringify(err))
}
}
this.sse.onerror = (error) => {
// Message.error("SEE连接错误");
};
}
发起的请求并没有携带Authorization请求头,导致JWT无法进行认证。
二、解决方案
几经搜索查阅文档,发现浏览器原生的EventSource API不支持自定义请求头,推荐使用EventSourcePolyfill这个JavaScript库。
# 安装
npm i event-source-polyfill
EventSource发起的请求是eventsource类型,而EventSourcePolyfill的请求用的是fetch。把EventSource替换成EventSourcePolyfill就可以携带Authorization请求头了。
/**
* 初始化仪表盘数据
*/
async initDashboard() {
// 原生EventSource不支持修改请求头
this.sse = new EventSourcePolyfill(this.baseUrl + '/dashboard', {
withCredentials: true,
headers: {
'Authorization': `Bearer ${getToken()}`
},
heartbeatTimeout: 10 * 1000, // 超时重连时间,单位毫秒
});
this.sse.onmessage = (event) => {
try {
if (event.data && typeof event.data === 'string') {
const res = JSON.parse(event.data);
const { visit = [], comment, union, product = [], network } = res.data;
// 处理数据方法
// ...
}
} catch (err) {
console.log('SEE初始化异常', JSON.stringify(err))
}
}
this.sse.onerror = (error) => {
// Message.error("SEE连接错误");
};
},