Nodejs node+socket.io+redis构建消息推送服务的跨域问题
Nodejs node+socket.io+redis构建消息推送服务的跨域问题
用node+socket.io+redis构建了一个消息推送服务。其他项目都通过jquery的$.getScript()方式载入服务上的socket.io.js和一个封装的api脚本message.js,然后初始化的时候传入回调函数获取消息数量及消息展示方式。
在所有标准浏览器上都没问题。不管是不是同域下。但在ie下就不行。只有在同域(我测试的时候是同ip)下是没问题的。
个人觉得是socket.io的机制,因为在ie下没有用websocket,所以产生问题。有做过类似的给点意见吗?
0906补充
我发在github socket.io 上的问题描述 v 0.99 my node server on http://192.168.1.186:6789
my web server on http://192.168.1.14:85
*router code
app.get('/api', function (req, res) {
var _userid = req.query.userid;
req.session.userid = _userid;
fs.readFile('./node_modules/socket.io/node_modules/socket.io-client/dist/socket.io.min.js', 'utf-8', function (err, data1) {
if (err)
console.log(err);
else {
fs.readFile('./public/javascripts/message.js', 'utf-8', function (err, data2) {
if (err)
console.log(err);
else {
res.setHeader('content-type', 'application/x-javascript; charset=UTF-8');
res.end(data1 + data2);
}
});
}
});
*message.js code
var socket;
var serverHost='http://192.168.1.186';
var serverPort='6789'
$(function () {
socket = io.connect(serverHost, { port:serverPort });
socket.on('connect', function () {
console.info('socket success!');
});
*client code
$.getScript("http://192.168.1.186:6789/api?userid=1265",function(){
//notice.init({userid:_1265,getNoticeNum:IBD.util.getNoticeNum,showNotice:IBD.util.showNotice});
});
all the code can work well in firefox and chrome ,but in ie
io.set(‘authorization’, function (hsData, accept) {
console.log(hsData.headers.cookie) // undefined
})
hao can i solve the problem or where is the problem? thank you!
i’m so sorry my english is so poor
再次补充
在ie下,如果忽略掉hsData.headers.cookie而直接创建socket.io是没有问题的,flashsocket,xhr-polling,jsop-polling都可以通过,现在的问题就是,这种跨域的获取方式在ie下无法获取到hsData.headers.cookie,怎样才能解决.
针对你提到的问题,即在使用 Node.js
、Socket.IO
和 Redis
构建的消息推送服务中遇到的跨域问题,特别是在 Internet Explorer 中遇到的问题,可以通过一些配置调整来解决。这里主要涉及的是 Socket.IO
的跨域处理以及如何正确设置 HTTP 响应头以允许跨域请求。
解决方案概述
- 配置 Socket.IO 允许跨域:确保你的
Socket.IO
服务器正确配置了 CORS(跨源资源共享),允许来自不同域的连接。 - HTTP 响应头设置:确保你的服务器响应头中包含了必要的 CORS 相关字段,如
Access-Control-Allow-Origin
。
示例代码
Node.js 服务器端代码
const express = require('express');
const http = require('http');
const socketIo = require('socket.io');
const redisAdapter = require('socket.io-redis');
const app = express();
const server = http.createServer(app);
const io = socketIo(server);
// 配置 Redis 适配器
io.adapter(redisAdapter({
host: 'localhost',
port: 6379,
}));
// 设置 CORS
io.origins('*:*'); // 允许所有来源
// 启用 CORS
io.engine.on('headers', (headers, req) => {
headers.push('Access-Control-Allow-Origin: *');
headers.push('Access-Control-Allow-Methods: GET, POST, OPTIONS');
headers.push('Access-Control-Allow-Headers: Content-Type, Authorization');
});
io.on('connection', (socket) => {
console.log('A user connected');
socket.on('disconnect', () => {
console.log('User disconnected');
});
// 其他事件监听
});
server.listen(6789, () => {
console.log('Server listening on port 6789');
});
客户端代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Socket.IO Client</title>
<script src="https://cdn.socket.io/4.0.0/socket.io.min.js"></script>
<script src="message.js"></script>
</head>
<body>
<script>
$(document).ready(function () {
var socket = io('http://192.168.1.186:6789', {
transports: ['polling'] // 强制使用 polling 连接
});
socket.on('connect', function () {
console.info('Socket connected successfully!');
});
});
</script>
</body>
</html>
解释
- CORS 配置:在
io.origins('*:*')
中,*:*
表示允许所有来源的所有端口进行连接。这通常用于开发环境。生产环境中,建议指定具体的来源。 - HTTP 响应头:通过
io.engine.on('headers', ...)
方法添加 CORS 相关的 HTTP 响应头,确保客户端能够正确接收来自服务器的数据。 - 强制使用 polling 连接:由于某些旧版浏览器(如 IE)不支持 WebSocket,我们可以在客户端强制使用 polling 连接,这可以确保兼容性。
以上配置应该能帮助你在 IE 中解决跨域问题。希望这对你有所帮助!
怎么没有人给点意见!!!!自己不停的测试发现,在ie下,我开着开发者工具(F12)运行,就可以创建socket。悲催!!!什么原因!!!
这边前端不多啊, 而且高人都不怎么逛论坛的… 记得有看到过说 IE 下要到刷新时候才有连接的… 论坛里搜了下没搜到
高人不是不逛论坛,而是很低调,绝世高手都这样
socket.io支持的浏览器范围很广,对不支持websocket的浏览器它会降级处理的. 比如说 JSONP 轮询,除非你用的是IE5 = =
JSONP是一直存在的,不过不是用来轮询,是用来做跨域处理的。
我这在所有的浏览器上都是ok的。应该是你的node服务有问题。如果不行的话你可以把socket.io这个js文件放在你的网站里部署。
我也发现了可能是引用的问题,因为socket的请求地址http://192.168.1.186:6789/socket.io/1/?t526429472在ie下第一次访问是握手失败,刷新下,就可以成功!!!!有人遇到这样的问题没有!!!!
我这在所有的浏览器上都是ok的。应该是你的node服务有问题。如果不行的话你可以把socket.io这个js文件放在你的网站里部署。
这样不不能做成服务了,其他项目要用通知还要在自己的项目中部署socket.io。我只是想完全做成服务,类似google的好多服务那种模式
顶起来!
…
…
LZ 你用flashsocket怎么配置的?我怎么调都不成功啊〜望指点,多谢〜
io.configure(function () {
io.enable('browser client minification'); // send minified client
io.enable('browser client etag'); // apply etag caching logic based on version number
io.enable('browser client gzip'); // gzip the file
//io.set('log level', 1); // reduce logging
//io.set("origins","*");
io.set('transports', [ // enable all transports (optional if you want flashsocket)
'websocket'
, 'flashsocket'
, 'htmlfile'
, 'xhr-polling'
, 'jsonp-polling'
]);
//io.set('store', new sio.RedisStore({port:config.redis.port,host:config.redis.host}));
});
我现在也在做类似的项目,站Ai向站B发请求,然后将A发过去的信息推送到B的客户端,现在还不知道咋整呢,
跨域如何调用呢
主要问题是你这个cookie跨域吧?你到底需要cookie里的什么东西呢,可不可以你自己种一个cookie到客户端用?
我是进来看解决方案的。。。结果讨论了半天还没结果。。。
针对您提到的跨域问题,主要涉及到两个方面:Socket.IO 的跨域配置以及 IE 浏览器对 Cookie 的处理。
解决方法
1. 配置 Socket.IO 跨域
首先确保您的 Node.js 服务器正确地设置了 CORS(跨源资源共享)策略。可以通过设置 socket.io
的 origins
属性来允许特定的来源。
const io = require('socket.io')(server, {
cors: {
origin: "http://192.168.1.14:85",
methods: ["GET", "POST"]
}
});
2. 处理 IE 浏览器的 Cookie 问题
在 IE 中,由于安全原因,跨域请求可能不会发送 Cookie。为了确保 Cookie 可以正常发送,可以使用以下方法:
客户端代码
在 IE 中,您需要确保请求包含 withCredentials
设置为 true
,以便跨域请求能够携带 Cookie。
socket = io.connect(serverHost, {
port: serverPort,
transports: ['polling'], // 确保使用 polling 方式
forceNew: true,
'forceNew': true,
'reconnection': false,
'reconnectionDelay': 1000,
'reconnectionDelayMax': 5000,
'reconnectionAttempts': 1,
withCredentials: true // 这个很重要
});
服务器端代码
确保服务器返回的响应中包含了 Access-Control-Allow-Credentials
标头。
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', 'http://192.168.1.14:85');
res.header('Access-Control-Allow-Credentials', 'true');
res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
next();
});
总结
通过上述步骤,您可以确保在 IE 浏览器中跨域请求能够正常工作,并且能够携带 Cookie。这样应该可以解决您遇到的问题。如果还有其他问题或需求,请进一步告知。