解决Nodejs socket.io is not allowed by Access-Control-Allow-Origin 跨域问题

发布于 1周前 作者 phonegap100 来自 nodejs/Nestjs

解决Nodejs socket.io is not allowed by Access-Control-Allow-Origin 跨域问题

解决nodejs socket.io is not allowed by Access-Control-Allow-Origin 跨域问题 blog:http://www.cnblogs.com/solq/ demo:http://unitysgui.sinaapp.com/websocket/socketio.html

更改 :\node_modules\socket.io\lib\manager.js

if (origin) { // https://developer.mozilla.org/En/HTTP_Access_Control headers[‘Access-Control-Allow-Origin’] = origin; headers[‘Access-Control-Allow-Credentials’] = ‘true’; //headers[‘Access-Control-Allow-Headers’] = ‘Referer’; } headers[‘Access-Control-Allow-Origin’] = “*”;

在后面添加 headers[‘Access-Control-Allow-Origin’] = “*”;

server.js

var http = require(‘http’),
io = require(‘socket.io’), sys = require(‘sys’);

server = http.createServer(function(req, res){ res.writeHead(200, {‘Content-Type’: ‘text/html’}); res.end(“hello”); }); server.listen(8082);

var socket = io.listen(server,{origins: ‘:’});

/* socket.set(“origins”,""); socket.set(‘transports’, [ ‘websocket’ , ‘flashsocket’ , ‘htmlfile’ , ‘xhr-polling’ , ‘jsonp-polling’ ]);/

socket.on(‘connection’, function(client){

sys.puts("New client is here!");
client.send("hello world");

client.on(‘message’, function(msg){ sys.puts(“client has sent:”+msg); }) ; client.on(‘disconnect’, function(){ sys.puts(“Client has disconnected”); }) ;

//发送自定义事件 client.emit(‘news’, { hello: news world });

//临听自定义事件 client.on(‘my other event’, function (data) { //console.log(data); });

});

client.js

<script src=“http://localhost:8082/socket.io/socket.io.js”></script> <script> window.onload=function(){

var url='127.0.0.1:8082';
var socket = io.connect('localhost',{port:8082,rememberTransport:true,timeout:1500});
//var socket = new io.Socket(null,{port:8082,rememberTransport:true,timeout:1500});

/* if (/Firefox/\s/.test(navigator.userAgent)){ var socket = io.connect(url,{transports:[‘xhr-polling’]}); } else if (/MSIE (\d+.\d+);/.test(navigator.userAgent)){ var socket = io.connect(url,{transports:[‘jsonp-polling’]}); } else { var socket = io.connect(url,{transports:[‘websocket’]}); } */

//socket.connect(); socket.on(‘connect’, function(){ console.log(‘connected to server++++++++++++++++’); socket.send(‘Hi Server…’); }) ; socket.on(‘message’, function®{ console.log(‘msg:+++++++++++’+r); }) ; socket.on(‘disconnect’, function(){ console.log(‘disconnected from server’); }) ;

socket.on(‘news’, function (data) { console.log("++++++++++++++++++++++++++"); console.log(data);

//发送自定义事件
socket.emit('my other event', { my: 'data' });

});

/XMLHttpRequest cannot load http://localhost:8082/socket.io/1/?t=1336306289263. Origin null is not allowed by Access-Control-Allow-Origin. var ws = new WebSocket(“ws://127.0.0.1:8082”); ws.onopen = function(){console.log(‘connected to server’);} ws.onmessage = function(m){console.log(‘onmessage’);} ws.onclose = function(){}/

} </script>

https://github.com/LearnBoost/Socket.IO/wiki/Configuring-Socket.IO 注意:经过测试 io.connect(‘localhost’) localhost:8082 加上端会连不上

经过测试。。

if (origin!=‘null’) { // https://developer.mozilla.org/En/HTTP_Access_Control headers[‘Access-Control-Allow-Origin’] = origin; headers[‘Access-Control-Allow-Credentials’] = ‘true’; //headers[‘Access-Control-Allow-Headers’] = ‘Referer’; } console.log(“console.log(origin)+++++++++++++++++++++++++++++++++++++++”) console.log(origin) console.log(req.headers)

origin==null…难怪连不上。。。为什么为是null不太懂原理。。。就不管了,,手动改为全部可以访问就行了

解决IE不能接收服务端信息问题: sever 要打开这几个协议吧。。。。 然后 clinet html 要放在服务里面,因为IE用的是 jsonp 方式 的话。。。。。。。。。。。只要是 js 请求都要放在服务器… 但是放在服务器里, node server 接收 ie 客户端 连接类型为 flashsocket 方式,反正是不太了解。。。能工作就行了。。哈哈

socket.set(‘transports’, [ ‘websocket’ , ‘flashsocket’ , ‘htmlfile’ , ‘xhr-polling’ , ‘jsonp-polling’ ]);

最后,经过反复测试,,以上打开的协议是 遍历检测有就使用的。。。。 如果把 flashsocket 放在最后,那么 server 跟 ie 就用 jsonp 方式来连接…但是 ie 接收不了数据。。。。有人知道是什么原因,麻烦你告诉我。。好了谢谢…


12 回复

解决Nodejs Socket.io Access-Control-Allow-Origin 跨域问题

问题描述

在使用Socket.io时,经常遇到跨域问题。特别是当客户端与服务器不在同一个域名下时,浏览器会阻止请求,提示错误信息如:

XMLHttpRequest cannot load http://example.com/socket.io/. Origin http://anotherdomain.com is not allowed by Access-Control-Allow-Origin.

解决方案

要解决这个问题,我们需要配置Socket.io服务器,使其允许来自不同源的请求。可以通过修改Socket.io的默认行为来实现这一点。

修改Socket.io源码

首先,找到Socket.io模块中的manager.js文件,并在适当的位置添加以下代码:

if (origin) {
    headers['Access-Control-Allow-Origin'] = origin;
    headers['Access-Control-Allow-Credentials'] = 'true';
}

headers['Access-Control-Allow-Origin'] = "*";

这行代码的作用是确保所有来源的请求都能被接受。

示例代码

下面是完整的服务器端和客户端代码示例:

server.js

var http = require('http'),
    io = require('socket.io'),
    sys = require('util');

var server = http.createServer(function(req, res) {
    res.writeHead(200, {'Content-Type': 'text/html'});
    res.end("hello");
});
server.listen(8082);

var socket = io.listen(server, {origins: '*:*'});

socket.on('connection', function(client) {
    sys.puts("New client is here!");
    client.send("hello world");

    client.on('message', function(msg) {
        sys.puts("client has sent:" + msg);
    });

    client.on('disconnect', function() {
        sys.puts("Client has disconnected");
    });

    // 发送自定义事件
    client.emit('news', { hello: 'news world' });

    // 监听自定义事件
    client.on('my other event', function(data) {
        // console.log(data);
    });
});

client.js

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Socket.io Client</title>
</head>
<body>
    <script src="http://localhost:8082/socket.io/socket.io.js"></script>
    <script>
        window.onload = function() {
            var socket = io.connect('http://localhost:8082', { transports: ['websocket', 'flashsocket', 'htmlfile', 'xhr-polling', 'jsonp-polling'] });

            socket.on('connect', function() {
                console.log('connected to server++++++++++++++++');
                socket.send('Hi Server...');
            });

            socket.on('message', function(r) {
                console.log('msg:+++++++++++' + r);
            });

            socket.on('disconnect', function() {
                console.log('disconnected from server');
            });

            socket.on('news', function(data) {
                console.log("++++++++++++++++++++++++++");
                console.log(data);

                // 发送自定义事件
                socket.emit('my other event', { my: 'data' });
            });
        }
    </script>
</body>
</html>

关键点解释

  1. 修改Socket.io源码:通过修改manager.js文件,设置Access-Control-Allow-Origin*,以允许所有来源的请求。
  2. 服务器端配置:在创建Socket.io实例时,设置origins参数为'*:*',表示允许所有来源和端口的连接。
  3. 客户端配置:在客户端初始化Socket.io连接时,设置transports参数为多个传输方式,以确保兼容性。

通过上述步骤,可以有效解决Socket.io的跨域问题。


汗,,,怎么没得排版的。。。。。。。。。。。。。。。。

需要学习以下markdown语法

解决nodejs socket.io is not allowed by Access-Control-Allow-Origin 跨域问题

blog:http://www.cnblogs.com/solq/
demo:http://unitysgui.sinaapp.com/websocket/socketio.html

更改 :\node_modules\socket.io\lib\manager.js

if (origin) {
    // https://developer.mozilla.org/En/HTTP_Access_Control
    headers['Access-Control-Allow-Origin'] = origin;
    headers['Access-Control-Allow-Credentials'] = 'true';
    //headers['Access-Control-Allow-Headers'] = 'Referer';
  }
    headers['Access-Control-Allow-Origin'] = "*";

在后面添加 headers[‘Access-Control-Allow-Origin’] = “*”;

server.js

var http = require('http'),  
io = require('socket.io'),
sys = require('sys');

server = http.createServer(function(req, res){ res.writeHead(200, {‘Content-Type’: text/html’}); res.end(“hello”); }); server.listen(8082);

var socket = io.listen(server,{origins: :’});

/* socket.set(“origins”,""); socket.set(‘transports’, [ ‘websocket’ , ‘flashsocket’ , ‘htmlfile’ , ‘xhr-polling’ , ‘jsonp-polling’ ]);/

socket.on(‘connection’, function(client){

sys.puts("New client is here!");
client.send("hello world");

client.on('message', function(msg){ sys.puts("client has sent:"+msg); }) ;
client.on('disconnect', function(){ sys.puts("Client has disconnected"); }) ;

//发送自定义事件
client.emit('news', { hello: 'news world' });

//临听自定义事件
client.on('my other event', function (data) {
    //console.log(data);
});

});

client.js

<script src="http://localhost:8082/socket.io/socket.io.js"></script>
<script>
window.onload=function(){
    
    var url='127.0.0.1:8082';
    var socket = io.connect('localhost',{port:8082,rememberTransport:true,timeout:1500});
 
    socket.on('connect', function(){ 
        console.log('connected to server++++++++++++++++'); 
        socket.send('Hi Server...'); 
    }) ;
    socket.on('message', function(r){ console.log('msg:+++++++++++'+r); }) ;
    socket.on('disconnect', function(){ console.log('disconnected from server'); }) ;

    socket.on('news', function (data) {
        console.log("++++++++++++++++++++++++++");
        console.log(data);
        
        //发送自定义事件
        socket.emit('my other event', { my: 'data' });
    });
    
    /*XMLHttpRequest cannot load http://localhost:8082/socket.io/1/?t=1336306289263. Origin null is not allowed by Access-Control-Allow-Origin.
    var ws = new WebSocket("ws://127.0.0.1:8082");
    ws.onopen = function(){console.log('connected to server');}
    ws.onmessage = function(m){console.log('onmessage');}
    ws.onclose = function(){}*/
}
</script>

https://github.com/LearnBoost/Socket.IO/wiki/Configuring-Socket.IO

注意:经过测试 io.connect(‘localhost’) localhost:8082 加上端会连不上

 if (origin!='null') {
    // https://developer.mozilla.org/En/HTTP_Access_Control
    headers['Access-Control-Allow-Origin'] = origin;
    headers['Access-Control-Allow-Credentials'] = 'true';
    //headers['Access-Control-Allow-Headers'] = 'Referer';
  }
    console.log("console.log(origin)+++++++++++++++++++++++++++++++++++++++")
    console.log(origin)
    console.log(req.headers)

origin==null…难怪连不上。。。为什么为是null不太懂原理。。。就不管了,,手动改为全部可以访问就行了

解决IE不能接收服务端信息问题: sever 要打开这几个协议吧。。。。 然后 clinet html 要放在服务里面,因为IE用的是 jsonp 方式 的话。。。。。。。。。。。只要是 js 请求都要放在服务器… 但是放在服务器里, node server 接收 ie 客户端 连接类型为 flashsocket 方式,反正是不太了解。。。能工作就行了。。哈哈

socket.set('transports', [
    'websocket'
    , 'flashsocket'
    , 'htmlfile'
    , 'xhr-polling'
    , 'jsonp-polling'
]);

最后,经过反复测试,,以上打开的协议是 遍历检测有就使用的。。。。 如果把 flashsocket 放在最后,那么 server 跟 ie 就用 jsonp 方式来连接…但是 ie 接收不了数据。。。。有人知道是什么原因,麻烦你告诉我。。好了谢谢…

希望能给个邀请码。。。。。

… 楼上是发布者的话, 帖子描述的地方有个图标可以重新编辑帖子的…
而且全角句号连用看得人太纠结…

前几天我遇到这个问题搜到解决方案是这个(Chrome 20 上测试了…) http://stackoverflow.com/questions/6736706/socket-io-access-control-allow-origin-error-from-remote-site

io = require('socket.io').listen(app, {origins: '*:*'});

看楼主代码上这个还是注释了的(*个数不一样), 两个方案区别怎么样的?

如何用火孤或者google浏览器的话, clinet html 可以不用放在服务器里。。因为用的是 websocket连接方式。。。

我加了 {origins: ‘:’} 还是不行,所有就去掉了

这个看懂了, 好吧原来我看漏掉了… 除了注释那里意外还是有指定 origins 的…
IE 我没在用, 刚好事情都省了…

1、{origins: '*:*'}这句其实是没必要的,因为这是manager.js里面的默认值

2、headers['Access-Control-Allow-Origin'] = "*";这句也是没有必要的, 上面的headers['Access-Control-Allow-Origin'] = origin;已经足够了

至于跨域出现的问题首先要确保你的测试页面是放在服务器上的,如果是放在本机上的服务器,请求地址用127.0.0.1:xxxx 代替 localhost:xxxx,因为在跨域的时候,IE8以上优先用的不是jsonp,而是xhr-polling(XDomainRequest),因为XDomainRequest跨域请求localhost会拒绝访问

要解决 socket.io 的跨域问题(即 Access-Control-Allow-Origin 错误),你需要在服务器端配置响应头,允许来自不同源的请求。下面是基于你的描述,如何修改 Node.js 服务器端代码以支持跨域请求的步骤:

修改服务器端代码

在你的 server.js 文件中,你需要设置响应头以允许来自任何来源的请求:

var http = require('http');
var io = require('socket.io');
var path = require('path');

var server = http.createServer(function(req, res) {
    res.writeHead(200, {'Content-Type': 'text/html'});
    res.end("hello");
});

server.listen(8082);

var socket = io.listen(server);

// 设置允许跨域访问
socket.attach(server, {
    origins: '*:*',
    allowRequest: function (auth, callback) {
        const headers = auth.req.headers;
        const origin = headers.origin || headers.referer;
        return callback(null, !origin || origin.includes('your-allowed-domain'));
    }
});

socket.on('connection', function(client) {
    console.log("New client is here!");

    client.send("hello world");

    client.on('message', function(msg) {
        console.log("client has sent:" + msg);
    });

    client.on('disconnect', function() {
        console.log("Client has disconnected");
    });

    // 发送自定义事件
    client.emit('news', { hello: 'news world' });

    // 监听自定义事件
    client.on('my other event', function (data) {
        console.log(data);
    });
});

解释

  1. 设置跨域响应头:通过 socket.attach() 方法中的 allowRequest 回调函数,你可以检查请求的来源并决定是否允许该请求。这里我们简单地允许所有来源,但你可以根据需要限制到特定域名。

  2. 简化处理:你可以直接在 socket.attach 中设置 origins: '*' 来允许所有来源,如果你不需要复杂的验证逻辑。

  3. 客户端连接:客户端的 client.js 文件无需更改,因为它已经是正确的连接方式。

这样设置后,你的服务器将正确处理来自不同源的 socket.io 连接请求,并解决跨域问题。

回到顶部
AI 助手
你好,我是IT营的 AI 助手
您可以尝试点击下方的快捷入口开启体验!