Permessage-Deflate 扩展中断 Socket.io WebSocket 通信(400 错误请求)

Permessage-Deflate Extension Breaks Socket.io WebSocket Communication (400 Bad Request)

我需要为 websocket 通信启用压缩(使用 socketio)。我通过将 perMessageDeflate 设置为 true 来做到这一点,这在我的开发环境和临时服务器(使用 Wireshark 验证)上运行良好。但是,在我们的生产服务器上,websocket 连接失败并且 socketio (v4.4.1) 回退到轮询。两者都使用 nginx 作为具有相同配置的反向代理。 Chromium 控制台显示

WebSocket connection to 'wss://***/ws-test/socket.io/?EIO=4&transport=websocket&sid=9P4EelJhF0CcxvwNAAAE' failed: Error during WebSocket handshake: Unexpected response code: 400

我创建了一个显示相同行为的最小示例。服务器上的 Nodejs 应用程序:

const express = require('express');
const app = express();
const http = require('http');
const server = http.createServer(app);
const { Server } = require("socket.io");

const io = new Server(server, {
    perMessageDeflate: true
});

app.get('/', (req, res) => {
    res.sendFile(__dirname + '/index.html');
});

server.listen(3001, () => {
    console.log('listening on *:3001');
});

客户:

    ...
    <script src="socket.io/socket.io.js"></script>
    <script>
      var socketio_path = window.location.pathname + 'socket.io';
      var socket = io( { path: socketio_path } );
    </script>
</body>

错误400似乎来自nodejs服务器,而不是nginx。我启用了各种日志记录,但找不到任何相关消息。软件版本也相当接近和最新:nginx 1.18.0(暂存和生产),nodejs 14.19.0/14.18.1 (staging/prod)。您有什么想法可以帮助在生产服务器上完成这项工作吗?

事实证明,问题出在生产服务器上使用的 Azure 应用程序网关。当它被绕过时,websocket 连接(启用 perMessageDeflate)工作正常。

切换到更新版本的 Azure 应用程序网关(v2 而不是 v1)最终解决了这个问题。