Heroku部署Socket.IO/Node.js应用遇登录报错:Invalid endpoint
看起来你的问题主要集中在Socket.IO的端口配置、前后端事件名不匹配,以及部署后的连接地址错误这几个点上,结合你提供的代码,我来一步步帮你排查修复:
1. 事件名不匹配:前端监听的事件和后端发送的不一致
看你的代码就能发现一个明显的问题:后端Socket.IO发送的事件是output,但前端监听的是message,这直接导致前端收不到任何消息,甚至可能引发后续错误流程打到Express的根路由:
- 后端代码片段:
socket.emit('output', payload.toString()); // 发送的是output事件 - 前端代码片段:
this.socket.on('message', (data) => { observer.next(data); }); // 监听的是message事件
修复:把前端的监听事件改成output即可:
this.socket.on('output', (data) => { observer.next(data); });
2. Socket.IO与Express服务分离,端口不统一
你现在后端同时跑了两个独立服务:Express在8888端口,Socket.IO在8080端口。本地开发时两个端口都能正常访问,但部署后很容易出问题:
- 服务器防火墙大概率不会开放8080端口,导致Socket连接失败
- 前端硬编码
localhost:8080,部署后根本无法连接到远程服务器的Socket服务 - 两个端口的跨域配置不统一,引发跨域错误
修复:将Socket.IO挂载到Express服务上,共用同一个端口,简化配置:
修改app.js的代码:
const express = require('express'); const app = express(); const path = require('path'); const bodyParser = require('body-parser'); const cors = require('cors'); const passport = require('passport'); const AWS = require('aws-sdk'); var dynamoose = require('dynamoose'); var awsIot = require('aws-iot-device-sdk'); // 新增:创建HTTP服务器,把Express挂载上去 const http = require('http'); const server = http.createServer(app); // 把Socket.IO挂载到HTTP服务器上,同时配置CORS(部署后替换origin为你的前端生产域名) const io = require('socket.io')(server, { cors: { origin: 'http://localhost:4200', credentials: true } }); const client = io.sockets; // 其余原有代码保持不变... // 最后把app.listen改成server.listen,让Express和Socket.IO共用一个端口 server.listen(port, host, () => { console.log("Server listening on: " + port) }); // 后面的Socket连接逻辑不变 client.on('connection', function(socket){ device.on('message', function(topic, payload) { socket.emit('output', payload.toString()); }); });
3. 前端Socket连接地址硬编码为localhost
部署后前端还在请求http://localhost:8080,这显然无法连接到远程服务器的Socket服务,甚至可能把请求误发到本地的无效服务,最终触发后端的"Invalid endpoint"提示。
修复:改成动态获取服务器地址,或者直接用相对路径:
import { Injectable } from '@angular/core'; import { Subject } from 'rxjs/Subject'; import { Observable } from 'rxjs/Observable'; import * as io from 'socket.io-client'; @Injectable() export class SocketIOService { // 用相对路径,Socket.IO会自动适配当前页面的域名和端口 private url = '/'; private socket; getMessages() { let observable = new Observable(observer => { this.socket = io(this.url); this.socket.on('output', (data) => { observer.next(data); }); return () => { this.socket.disconnect(); }; }) return observable; } }
4. 部署环境的额外检查
- 确保服务器开放了Express/Socket.IO共用的端口(比如8888)
- 如果使用Nginx等反向代理,需要配置WebSocket支持,避免请求被拦截到Express的根路由
- 确认生产环境的CORS配置中的origin是前端的实际域名,不要保留localhost
做完这些修改后,重新部署应该就能解决登录时触发"Invalid endpoint"的问题了——大概率是之前Socket连接失败后,前端的错误请求误打到了Express的根路由导致的。
内容的提问来源于stack exchange,提问作者user8871219
相关产品推荐
相关产品推荐

