背景
SSE(Server-Sent Events)是一种浏览器与服务器之间单向通信的技术,通常使用在实时性要求较高的场景中,例如在线聊天、股票行情等。在 SSE 中,浏览器通过 EventSource 对象与服务器建立连接,服务器不断发送数据到浏览器,浏览器通过 EventSource 事件监听数据并显示。SSE 的优点在于无需像 WebSocket 一样建立双向通信,节省了服务器资源,同时也不会像轮询那样频繁发送请求,在实时性和节省资源之间取得了平衡。
然而,SSE 在 Safari 浏览器上有一个普遍的问题,就是会出现错误码 404(Not Found),导致连接失败,无法接收服务器发送的数据。这个问题一直困扰着前端开发人员,本文将探讨这个问题的原因以及解决方案。
原因
错误码 404,即请求的资源不存在,通常出现在服务器无法找到请求的文件或路由时。在 SSE 的情况下,Node.js 服务器在接收 SSE 连接请求时,会默认返回一个 200 的状态码,并返回一些头部信息以及一个数据流,开启 SSE。这与 WebSocket 不同,WebSocket 需要在服务器端进行协议升级(Upgrade)才能正式建立连接。因此,在 SSE 连接的过程中,由于可能存在多个后端路由的情况,一定要谨慎处理路由路径,确保路径正确。
在 Safari 浏览器中,发现错误码 404 的问题通常是由路由处理不当导致的。我们常常使用 Express 框架进行开发,同时也会使用到它的中间件功能。Express 提供了一个名为 express.static 的中间件,用于托管静态文件。使用该中间件时,一定要将路由路径限制在静态文件目录内,否则就会出现 404 错误。
例如,我们有一条 SSE 连接的路由如下:
-- -------------------- ---- ------- --------------- ------------- ---- - ------------------ - --------------- -------------------- ---------------- ----------- ------------- ------------ --- ---------------------- - ---------------- - - --- ------ - -------- -- ------ ---
在该路由中,我们希望每秒钟向浏览器发送当前时间。但如果该路由在 express.static 中间件之后,例如:
app.use(express.static(path.join(__dirname, 'public'))); app.get('/sse', function(req, res) { // SSE 代码 });
那么访问 /sse 时就会直接返回 404 错误。因为 express.static 已经将访问 /public 下的静态文件托管起来了,除此之外的路由都不存在,因此就会返回 404 错误。
解决方案
避免 SSE 错误码 404 的方法很简单,就是将 SSE 的路由结构放在 express.static 中间件之前。下面是一个正确的示例:
app.get('/sse', function(req, res) { // SSE 代码 }); app.use(express.static(path.join(__dirname, 'public')));
在这个示例中,SSE 的路由在静态文件托管前面,SSE 中间件就能够正确地返回数据流,不会出现错误。此外,我们还可以使用 Express 的路由前缀功能,确保路由正确,示例如下:
app.use('/api', function(req, res, next) { // 处理 SSE、WebSocket 路由 }); app.use(express.static(path.join(__dirname, 'public')));
在这个示例中,我们将 SSE 和 WebSocket 的路由统一以 /api 作为前缀,这样就能确保路由的正确性。
总结
SSE 是一种非常实用的技术,在实时性要求较高且需要节省服务器资源的情况下非常适用。然而,在 Safari 浏览器上可能会出现错误码 404 的问题,这通常是由于路由处理不当导致的。我们可以通过正确放置路由、使用路由前缀等方法来避免这种错误的出现。希望本文能够帮助读者更好地理解 SSE,并解决相关问题。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/6483059748841e98942616aa