单元测试 socket.io 的鉴权

       后端测试代码中,由于http请求中没有带上cookie,所以导致测试的过程中,总是会注释掉auth的代码。在不同角色用户登录过程中,socket.io就需要根据角色来判断用户的请求是不是合法的,这样就必须测试auth代码。在浏览器中测试较为复杂,在经过多种尝试后发现其实是有办法来在测试代码中完成任务的。

模拟请求

模拟请求使用 request,

var request = require('request');  
var cookies = request.jar();  
request.get(  
    {
        url: 'http://url',
        jar: cookies
    },
    function (err, res, body) {
        if (err) {
            console.log('Error: ', err);
            process.exit(0);
        }
        io = require('socket.io-client')('http://url',{forceNew: true, reconnectionAttempts:5,reconnectionDelay:2000 ,  timeout: 10000});
        // socket on code
    }
);

       发现socket.io请求过程中没有能够带上cookie,导致无法express的相关插件无法解析cookie中的数据,无法完成鉴权服务。

分析过程

       查找了stackoverflow.com上的帖子,发现版本都比较旧,得到的内容都是告诉大家如何鉴权,而不是如何测试鉴权。

       gist上的帖子 socket-io.client send the cookies 使用的版本过低,在使用socket.io 1.7.3的版本,发现无法测试通过。如果是较低版本的socket.io可以参考一下。

       后续只能求助于源码,显示查看了socket.io-client 的测试代码,发现没有相关内容,然后去查找了 engine.io-client 的源码,找到了一点启示代码。

var headers = {  
    'X-Custom-Header-For-My-Project': 'my-secret-access-token',
     'Cookie': 'user_session=NI2JlCKF90aE0sJZD9ZzujtdsUqNYSBYxzlTsvdSUe35ZzdtVRGqYFr0kdGxbfc5gUOkR9RGp20GVKza; path=/; expires=Tue, 07-Apr-2015 18:18:08 GMT; secure; HttpOnly'
};

var polling = new eio.transports.polling({  
    path: '/engine.io',
    hostname: 'localhost',
    extraHeaders: headers
});

       注意到了在transports中有 extraHeaders 的参数。所以就稍微修改了一下 socket.io 的请求,添加参数extraHeaders参数。

request.get(  
    {
        url: 'http://url',
        jar: cookies
    },
    function (err, res, body) {
        if (err) {
            console.log('Error: ', err);
            process.exit(0);
        }
        io = require('socket.io-client')('http://url',{forceNew: true, reconnectionAttempts:5,reconnectionDelay:2000 ,  timeout: 10000, 
        extraHeaders: {
            'Cookie': res.headers['set-cookie']
        }});
        // socket on code
    }
);

       启动测试代码,发现带入了请求的cookie,然后能够通过相关的匿名用户的测试了,如果是模拟用户登录,只需要吧get修改为post,把相关的cookie set到response中就可以了。

部分package.json依赖:
"dependencies": {
    "socket.io": "^1.7.3",
    "socket.io-client": "^1.7.3",
    "request": "2.79.0"
}
参考资料