Nest.js集成WebSocket配置后浏览器端连接失败问题咨询
问题根因
- 协议适配不匹配:
@WebSocketGateway()默认基于socket.io实现,和浏览器原生WebSocketAPI协议不兼容,原生客户端无法直接握手连接。 - 连接参数错误:配置了
namespace: 'events'但连接地址未携带命名空间;本地开发未配置SSL证书时使用wss://协议会触发证书校验失败;未指定服务端口时默认请求443端口,和本地Nest服务实际监听端口(通常为3000)不匹配。 - 配置缺失:未开启跨域配置时浏览器会拦截跨域WS请求;未安装对应WebSocket适配依赖时网关不会正常启动。
可运行实现示例
方案1:使用默认socket.io适配(官方推荐,功能更完善)
- 安装依赖
npm i @nestjs/websockets @nestjs/platform-socket.io socket.io
- 网关代码(修正配置)
import { WebSocketGateway, SubscribeMessage, WebSocketServer, WsResponse } from '@nestjs/websockets'; import { from, Observable } from 'rxjs'; import { map } from 'rxjs/operators'; import { Server } from 'socket.io'; @WebSocketGateway({ path: '/api', namespace: 'events', cors: { origin: "*" } // 本地开发放开跨域限制 }) export class EventGateway { @WebSocketServer() server: Server; @SubscribeMessage('events') findAll(): Observable<WsResponse<number>> { return from([1, 2, 3]).pipe( map((item) => ({ event: 'events', data: item })), ); } @SubscribeMessage('identity') async identity(client: any, data: number): Promise<number> { return data; } }
确保EventGateway已加入AppModule的providers数组。
3. 客户端连接代码(使用socket.io-client)
先安装客户端依赖:npm i socket.io-client
import { io } from "socket.io-client"; // 替换3000为你Nest服务实际监听端口 const socket = io('ws://localhost:3000/events', { path: '/api' }); socket.on('connect', () => { console.log('连接成功,socketID:', socket.id); // 测试identity接口 socket.emit('identity', 123, res => console.log('identity返回值:', res)); // 监听服务端推送的events事件 socket.on('events', data => console.log('收到events数据:', data)); // 触发events事件 socket.emit('events'); }); socket.on('connect_error', err => console.log('连接异常:', err));
方案2:使用原生WS适配(支持浏览器原生WebSocket对象连接)
如果必须使用原生WebSocket API连接,替换默认适配器即可:
- 安装依赖
npm i @nestjs/platform-ws ws
- 在main.ts中注册WS适配器
import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; import { WsAdapter } from '@nestjs/platform-ws'; async function bootstrap() { const app = await NestFactory.create(AppModule); app.useWebSocketAdapter(new WsAdapter(app)); // 替换为原生ws适配器 await app.listen(3000); // 端口自行替换 } bootstrap();
- 修改网关配置(原生ws不支持namespace,删除该字段)
@WebSocketGateway({ path: '/api', }) export class EventGateway { // 原有业务逻辑无需修改 }
- 浏览器端原生连接代码
// 替换3000为实际服务端口,本地无证书用ws协议不要用wss const ws = new WebSocket('ws://localhost:3000/api'); ws.onopen = () => { console.log('连接成功'); // 原生ws需要手动序列化消息,Nest WS适配器默认识别{event: string, data: any}格式 ws.send(JSON.stringify({event: 'identity', data: 456})); ws.send(JSON.stringify({event: 'events', data: null})); }; ws.onmessage = msg => { const payload = JSON.parse(msg.data); console.log('收到消息:', payload); }; ws.onerror = err => console.log('连接异常:', err);
排查方向
- 启动Nest服务时查看控制台日志,确认网关成功启动,无依赖缺失、注册错误提示。
- 核对连接地址:端口和服务监听端口一致、本地开发用
ws://而非wss://、socket.io模式下路径和命名空间配置和服务端匹配。 - 检查网关跨域配置,本地开发可临时放开origin限制,部署时按实际域名配置白名单。
- 打开浏览器F12控制台,查看Network面板中WS请求的错误码:404对应路径配置错误、证书错误对应协议使用错误、CORS报错对应跨域配置缺失。
- 使用socket.io模式时,确保客户端和服务端socket.io大版本一致,版本不兼容会导致握手失败。
内容的提问来源于stack exchange,提问作者Dev chimp
相关产品推荐
相关产品推荐

