/* | |
* Little example of how to use ```socket-io.client``` and ```request``` from node.js | |
* to authenticate thru http, and send the cookies during the socket.io handshake. | |
*/ | |
var io = require('socket.io-client'); | |
var request = require('request'); | |
/* | |
* This is the jar (like a cookie container) we will use always | |
*/ | |
var j = request.jar(); | |
/* | |
* First I will patch the xmlhttprequest library that socket.io-client uses | |
* internally to simulate XMLHttpRequest in the browser world. | |
*/ | |
var originalRequest = require('xmlhttprequest').XMLHttpRequest; | |
require('xmlhttprequest').XMLHttpRequest = function(){ | |
originalRequest.apply(this, arguments); | |
this.setDisableHeaderCheck(true); | |
var stdOpen = this.open; | |
/* | |
* I will patch now open in order to set my cookie from the jar request. | |
*/ | |
this.open = function() { | |
stdOpen.apply(this, arguments); | |
var header = j.get({ url: 'http://localhost:9000' }) | |
.map(function (c) { | |
return c.name + "=" + c.value; | |
}).join("; "); | |
this.setRequestHeader('cookie', header); | |
}; | |
}; | |
/* | |
* Authenticate first, doing a post to some url | |
* with the credentials for instance | |
*/ | |
request.post({ | |
jar: j, | |
url: 'http://localhost:9000/login', | |
form: {username: 'jose', password: 'Pa123'} | |
}, function (err, resp, body){ | |
/* | |
* now we can connect.. and socket.io will send the cookies! | |
*/ | |
var socket = io.connect('http://localhost:9000'); | |
socket.on('connect', function(){ | |
console.log('connected! handshakedddddddddddd') | |
done(); | |
})); | |
}); |
This comment has been minimized.
This comment has been minimized.
FYI. This no longer works with the latest version of And because you can't disable the header check, you can't set the cookie as the |
This comment has been minimized.
This comment has been minimized.
Thanks a lot for this. I ran into the same issue as @RunnerRick. The fix/hack I used was as follows:
var orig = require('xmlhttprequest');
require('$root/node_modules/socket.io-client/node_modules/xmlhttprequest').XMLHttpRequest = function () {
orig.apply(this, arguments);
// etc.
}; i.e. effectively override the In addition I needed to specify it('should do something', function (done) {
var sock = io.connect('xxx', { 'force new connection': true });
// ...
done();
});
it('should do something else', function (done) {
var sock = io.connect('xxx', { 'force new connection': true });
// ...
done();
}); |
This comment has been minimized.
This comment has been minimized.
I'm getting errors. Can you post your version of the code?
|
This comment has been minimized.
This comment has been minimized.
@codecowboy which version of |
This comment has been minimized.
This comment has been minimized.
TypeError: Object # has no method 'get' I'm getting this error with request v 2.33.0 |
This comment has been minimized.
This comment has been minimized.
You've probably figured it out by now, but here's the answer in case anyone else (such as myself) stumbles across this thread: replace:
with:
to reflect changes in the underlying cookie stores |
This comment has been minimized.
This comment has been minimized.
I've made this works for socket.io-client ~0.9. Is there a way to make it work for ~1.2 release? |
This comment has been minimized.
This comment has been minimized.
Some more hackery will be required for socket.io 1.0 as it does |
This comment has been minimized.
This comment has been minimized.
I was having the same issue and was able to get cookies working with 1.2.1 by creating a file containing the following: // XMLHttpRequest to override.
var xhrPath = 'socket.io-client/node_modules/engine.io-client/node_modules/xmlhttprequest';
// Make initial call to require so module is cached.
require(xhrPath);
var name = require.resolve(xhrPath);
// Get cached version.
var cachedXhr = require.cache[name];
var stdXhr = cachedXhr.exports;
// Callbacks exposes an object that callback functions can be added to.
var callbacks = {};
// Example
callbacks.test = function() {
console.log("In callback.");
}
var newXhr = function() {
stdXhr.apply(this, arguments);
for (method in callbacks) {
if (typeof callbacks[method] == "function") {
callbacks[method].apply(this, arguments);
}
}
}
newXhr.XMLHttpRequest = newXhr;
cachedXhr.exports = newXhr;
module.exports = newXhr;
module.exports.callbacks = callbacks; Requiring that and adding methods to var myXhr = require('./xmlhttprequest');
var io = require('socket.io-client');
/*
...
code which ends up with cookie value in myCookie
...
*/
myXhr.callbacks.test2 = function() {
this.setDisableHeaderCheck(true);
var stdOpen = this.open;
this.open = function() {
stdOpen.apply(this, arguments);
this.setRequestHeader('cookie', myCookie);
}
}
// Assuming uri was defined somewhere above.
var socket = io.connect(uri); It would also be possible, in the first file, to call |
This comment has been minimized.
This comment has been minimized.
Thank you chrahunt this is what I was looking for |
This comment has been minimized.
This comment has been minimized.
Complete exampleFor anyone that look for a complete example here is: First create a file: client-code.js process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
var request = require('request');
var cookies = request.jar();
var myXhr = require('./newXhr');
console.log('');
console.log('Request https://yourdomain.com/');
request.get(
{
url: 'https://yourdomain.com/',
jar: cookies
},
function (err, res, body) {
if (err) {
console.log('Error: ', err);
process.exit(0);
}
console.log('Status code: ', res.statusCode);
console.log('');
console.log('Headers: ', res.headers);
console.log('');
console.log('Cookies: ', cookies);
console.log('');
request.post(
{
url: 'https://yourdomain.com/login',
jar: cookies,
form: {
nick: 'secret_user',
password: 'yourpassword'
}
},
function (err, res, body) {
console.log('');
if (err) {
console.log('Error: ', err);
process.exit(0);
}
console.log('Status code: ', res.statusCode);
console.log('');
console.log('Headers: ', res.headers);
console.log('');
console.log('Cookies: ', cookies);
console.log('');
myXhr.callbacks.test2 = function () {
this.setDisableHeaderCheck(true);
var stdOpen = this.open;
this.open = function () {
stdOpen.apply(this, arguments);
this.setRequestHeader('Cookie', res.headers['set-cookie'][0].split(';')[0]);
}
}
var io = require("socket.io-client")("https://yourdomain.com/audience", {forceNew: true});
io.on('connect', function () {
console.log("Eureka !!!");
});
//process.exit(0);
});
}
); Now create new file called:newXhr.js thank you @chrahunt // XMLHttpRequest to override.
var xhrPath = 'socket.io-client/node_modules/engine.io-client/node_modules/xmlhttprequest';
// Make initial call to require so module is cached.
require(xhrPath);
var name = require.resolve(xhrPath);
// Get cached version.
var cachedXhr = require.cache[name];
var stdXhr = cachedXhr.exports;
// Callbacks exposes an object that callback functions can be added to.
var callbacks = {};
// Example
callbacks.test = function () {
console.log("In callback.");
}
var newXhr = function () {
stdXhr.apply(this, arguments);
for (method in callbacks) {
if (typeof callbacks[method] == "function") {
callbacks[method].apply(this, arguments);
}
}
}
newXhr.XMLHttpRequest = newXhr;
cachedXhr.exports = newXhr;
module.exports = newXhr;
module.exports.callbacks = callbacks; The dependencies package.json {
"name": "client-code",
"version": "1.0.0",
"description": "",
"main": "client-code.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"dependencies": {
"request": "^2.55.0",
"socket.io-client": "^1.1.0",
"xmlhttprequest": "^1.5.0"
}
} In Windows Unix base Tested with socket.io v1.1.0 Cheers! |
This comment has been minimized.
This comment has been minimized.
I fixed the cookie issue in socket-io-client 1.3.6 by overriding the http.ClientRequest constructor.
|
This comment has been minimized.
This comment has been minimized.
This solution does not work when you have multiple socket.io clients in the same node instance. If the clients auth as different users, overriding the cookie in the common |
This comment has been minimized.
This comment has been minimized.
For those that are still ending up here, using a newer version of SocketIO client may be better for you. This pull requests outlines how you can set cookies using the library directly: rakeshok/socket.io-client-cookie#9 Posting the code from the pull request here as well:
|
This comment has been minimized.
This comment has been minimized.
Sending cookies across origins is disabled in browsers (I believe at a lower level than any patching could allow). <!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Cookies</title>
<script>
window.addEventListener('load', function(event) {
let exist = document.getElementById("exist");
exist.textContent = document.cookie;
let mycookie = "mysession=abc123";
let elem = document.getElementById("cook");
elem.textContent = mycookie;
document.cookie = mycookie;
// let url = "https://www.google.ca/";
let url = "http://localhost:30080/";
let urlelem = document.getElementById("url");
urlelem.textContent = url;
let respelem = document.getElementById("resp");
let req = new Request(url, { credentials: "same-origin" });
fetch(req).then(function(resp) {
return resp.text();
}).then(function(text) {
respelem.textContent = text;
});
});
</script>
</head>
<body>
<p>
Existing document cookies <code id="exist"></code>.
<p>
Sending a cookie <code id="cook"></code> to URL <code id="url"></code>.
<p>
Response text: <code id="resp"></code>.
</body>
</html>
The browser's console shows the cookie being sent (when using the same origin as a destination).
|
This comment has been minimized.
Thank you so much for your work on Passport-SocketIO!
I had to change line 20 to use the xmlhttprequest bundled with socket.io-client.
Line 20: require('socket.io-client/node_modules/xmlhttprequest').XMLHttpRequest = . . .