CloudFront+NLB连接ECS Fargate(NestJS)的WebSocket异常排查
解决CloudFront下Socket.io与NestJS握手400及连接异常问题
当前React前端通过CloudFront访问NestJS后端Socket.io服务时,出现HTTP握手400状态码,直接连接NLB则正常,问题根源在于CloudFront默认未配置WebSocket所需的请求转发规则。以下是针对性修复步骤:
一、调整CloudFront行为配置
CloudFront默认不会转发WebSocket握手必需的请求头,需修改分发的行为(Behavior):
- 为Socket.io路径(如
/socket.io/*)创建独立行为(或修改全局行为):- 设置查看协议策略为
HTTPS Only,确保前端用WSS协议发起连接 - 配置缓存策略为
Managed-CachingDisabled,避免Socket.io请求被缓存 - 在源请求策略中,添加以下必需请求头到转发列表:
UpgradeConnectionHostX-Forwarded-ForX-Forwarded-Proto
这些头是后端识别WebSocket握手请求的核心依据,缺失会导致握手失败返回400。
- 设置查看协议策略为
二、确认CloudFront与NLB的协议适配
- 确保CloudFront的源协议策略设置为
HTTP Only,因为后端NestJS运行在80端口HTTP服务上 - NLB监听器保持TCP:80转发到目标组的配置不变,TCP协议可完整保留WebSocket的请求帧
三、NestJS Gateway适配配置
在NestJS的Socket.io Gateway中启用代理支持,识别CloudFront转发的请求头:
@WebSocketGateway({ cors: { origin: ['你的前端域名'], credentials: true, }, transports: ['websocket', 'polling'], allowEIO3: true, // 适配socket.io-client v3/v4版本 proxy: true, // 启用代理模式,解析X-Forwarded-*头 }) export class YourGateway { // Gateway逻辑代码 }
四、验证流程
- 等待CloudFront分发部署完成(约10-15分钟)
- 前端使用WSS协议发起连接:
const socket = io('https://你的CloudFront域名', { transports: ['websocket', 'polling'], withCredentials: true }); - 检查浏览器网络面板:确认
/socket.io/?EIO=4&transport=polling请求返回200,且WSS连接状态为Open - 查看CloudWatch日志,确认NestJS输出「Connected: user id」日志
内容的提问来源于stack exchange,提问作者mortvicious
相关产品推荐
相关产品推荐

