Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow configuration of Access-Control-Allow-Origin value #511

Merged
merged 3 commits into from
Nov 2, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ to a single process.
- `maxHttpBufferSize` (`Number`): how many bytes or characters a message
can be, before closing the session (to avoid DoS). Default
value is `10E7`.
- `origins` (`String`): the allowed origins (`*`)
- `allowRequest` (`Function`): A function that receives a given handshake
or upgrade request as its first parameter, and can decide whether to
continue or not. The second argument is a function that needs to be
Expand Down
26 changes: 17 additions & 9 deletions lib/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ function Server (opts) {
this.allowUpgrades = false !== opts.allowUpgrades;
this.allowRequest = opts.allowRequest;
this.cookie = false !== opts.cookie ? (opts.cookie || 'io') : false;
this.origins = opts.origins || '*';
this.cookiePath = false !== opts.cookiePath ? (opts.cookiePath || '/') : false;
this.cookieHttpOnly = false !== opts.cookieHttpOnly;
this.perMessageDeflate = false !== opts.perMessageDeflate ? (opts.perMessageDeflate || true) : false;
Expand Down Expand Up @@ -221,7 +222,7 @@ Server.prototype.handleRequest = function (req, res) {
var self = this;
this.verify(req, false, function (err, success) {
if (!success) {
sendErrorMessage(req, res, err);
self.sendErrorMessage(req, res, err);
return;
}

Expand All @@ -242,7 +243,7 @@ Server.prototype.handleRequest = function (req, res) {
* @api private
*/

function sendErrorMessage (req, res, code) {
Server.prototype.sendErrorMessage = function (req, res, code) {
var headers = { 'Content-Type': 'application/json' };

var isForbidden = !Server.errorMessages.hasOwnProperty(code);
Expand All @@ -254,20 +255,21 @@ function sendErrorMessage (req, res, code) {
}));
return;
}

headers['Access-Control-Allow-Origin'] = this.origins;
headers['Vary'] = 'Origin';
if (req.headers.origin) {
headers['Access-Control-Allow-Credentials'] = 'true';
headers['Access-Control-Allow-Origin'] = req.headers.origin;
} else {
headers['Access-Control-Allow-Origin'] = '*';
}

if (res !== undefined) {
res.writeHead(400, headers);
res.end(JSON.stringify({
code: code,
message: Server.errorMessages[code]
}));
}
}
};

/**
* generate a socket id.
Expand All @@ -293,9 +295,12 @@ Server.prototype.handshake = function (transportName, req) {
var id = this.generateId(req);

debug('handshaking client "%s"', id);
var opts = {
origins: this.origins
};

try {
var transport = new transports[transportName](req);
var transport = new transports[transportName](req, opts);
if ('polling' === transportName) {
transport.maxHttpBufferSize = this.maxHttpBufferSize;
transport.httpCompression = this.httpCompression;
Expand All @@ -309,7 +314,7 @@ Server.prototype.handshake = function (transportName, req) {
transport.supportsBinary = true;
}
} catch (e) {
sendErrorMessage(req, req.res, Server.errors.BAD_REQUEST);
this.sendErrorMessage(req, req.res, Server.errors.BAD_REQUEST);
return;
}
var socket = new Socket(id, this, transport, req);
Expand Down Expand Up @@ -404,7 +409,10 @@ Server.prototype.onWebSocket = function (req, socket) {
// transport error handling takes over
socket.removeListener('error', onUpgradeError);

var transport = new transports[req._query.transport](req);
var opts = {
origins: this.origins
};
var transport = new transports[req._query.transport](req, opts);
if (req._query && req._query.b64) {
transport.supportsBinary = false;
} else {
Expand Down
4 changes: 3 additions & 1 deletion lib/transport.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,14 @@ function noop () {}
* Transport constructor.
*
* @param {http.IncomingMessage} request
* @param {Object} opts allows the origins option to be passed along
* @api public
*/

function Transport (req) {
function Transport (req, opts) {
this.readyState = 'open';
this.discarded = false;
this.origins = opts.origins;
}

/**
Expand Down
6 changes: 3 additions & 3 deletions lib/transports/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ exports.polling.upgradesTo = ['websocket'];
* @api private
*/

function polling (req) {
function polling (req, opts) {
if ('string' === typeof req._query.j) {
return new JSONP(req);
return new JSONP(req, opts);
} else {
return new XHR(req);
return new XHR(req, opts);
}
}
4 changes: 2 additions & 2 deletions lib/transports/polling-jsonp.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ module.exports = JSONP;
* @api public
*/

function JSONP (req) {
Polling.call(this, req);
function JSONP (req, opts) {
Polling.call(this, req, opts);

this.head = '___eio[' + (req._query.j || '').replace(/[^0-9]/g, '') + '](';
this.foot = ');';
Expand Down
9 changes: 4 additions & 5 deletions lib/transports/polling-xhr.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ module.exports = XHR;
* @api public
*/

function XHR (req) {
Polling.call(this, req);
function XHR (req, opts) {
Polling.call(this, req, opts);
}

/**
Expand Down Expand Up @@ -58,11 +58,10 @@ XHR.prototype.onRequest = function (req) {
XHR.prototype.headers = function (req, headers) {
headers = headers || {};

headers['Access-Control-Allow-Origin'] = this.origins;
headers['Vary'] = 'Origin';
if (req.headers.origin) {
headers['Access-Control-Allow-Credentials'] = 'true';
headers['Access-Control-Allow-Origin'] = req.headers.origin;
} else {
headers['Access-Control-Allow-Origin'] = '*';
}

return Polling.prototype.headers.call(this, req, headers);
Expand Down
4 changes: 2 additions & 2 deletions lib/transports/polling.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ module.exports = Polling;
* @api public.
*/

function Polling (req) {
Transport.call(this, req);
function Polling (req, opts) {
Transport.call(this, req, opts);

this.closeTimeout = 30 * 1000;
this.maxHttpBufferSize = null;
Expand Down
4 changes: 2 additions & 2 deletions lib/transports/websocket.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ module.exports = WebSocket;
* @api public
*/

function WebSocket (req) {
Transport.call(this, req);
function WebSocket (req, opts) {
Transport.call(this, req, opts);
var self = this;
this.socket = req.websocket;
this.socket.on('message', this.onData.bind(this));
Expand Down
16 changes: 8 additions & 8 deletions test/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ describe('server', function () {
expect(res.body.code).to.be(0);
expect(res.body.message).to.be('Transport unknown');
expect(res.header['access-control-allow-credentials']).to.be('true');
expect(res.header['access-control-allow-origin']).to.be('http://engine.io');
expect(res.header['access-control-allow-origin']).to.be('*');
done();
});
});
Expand All @@ -75,7 +75,7 @@ describe('server', function () {
expect(res.body.code).to.be(1);
expect(res.body.message).to.be('Session ID unknown');
expect(res.header['access-control-allow-credentials']).to.be('true');
expect(res.header['access-control-allow-origin']).to.be('http://engine.io');
expect(res.header['access-control-allow-origin']).to.be('*');
done();
});
});
Expand Down Expand Up @@ -416,7 +416,7 @@ describe('server', function () {
expect(res.body.code).to.be(3);
expect(res.body.message).to.be('Bad request');
expect(res.header['access-control-allow-credentials']).to.be('true');
expect(res.header['access-control-allow-origin']).to.be('http://engine.io');
expect(res.header['access-control-allow-origin']).to.be('*');
done();
});
});
Expand Down Expand Up @@ -932,7 +932,7 @@ describe('server', function () {
it('should trigger transport close before open for ws', function (done) {
var opts = { transports: ['websocket'] };
listen(opts, function (port) {
var url = 'ws://%s:%d'.s('0.0.0.50', port);
var url = 'ws://%s:%d'.s('0.0.0.0', port);
var socket = new eioc.Socket(url);
socket.on('open', function () {
done(new Error('Test invalidation'));
Expand Down Expand Up @@ -2589,7 +2589,7 @@ describe('server', function () {

describe('cors', function () {
it('should handle OPTIONS requests', function (done) {
listen({handlePreflightRequest: true}, function (port) {
listen({handlePreflightRequest: true, origins: 'engine.io:*'}, function (port) {
request.options('http://localhost:%d/engine.io/default/'.s(port))
.set('Origin', 'http://engine.io')
.query({ transport: 'polling' })
Expand All @@ -2599,7 +2599,7 @@ describe('server', function () {
expect(res.body.code).to.be(2);
expect(res.body.message).to.be('Bad handshake method');
expect(res.header['access-control-allow-credentials']).to.be('true');
expect(res.header['access-control-allow-origin']).to.be('http://engine.io');
expect(res.header['access-control-allow-origin']).to.be('engine.io:*');
done();
});
});
Expand All @@ -2624,7 +2624,7 @@ describe('server', function () {
var headers = {};
if (req.headers.origin) {
headers['Access-Control-Allow-Credentials'] = 'true';
headers['Access-Control-Allow-Origin'] = req.headers.origin;
headers['Access-Control-Allow-Origin'] = '*';
} else {
headers['Access-Control-Allow-Origin'] = '*';
}
Expand All @@ -2642,7 +2642,7 @@ describe('server', function () {
expect(res.status).to.be(200);
expect(res.body).to.be.empty();
expect(res.header['access-control-allow-credentials']).to.be('true');
expect(res.header['access-control-allow-origin']).to.be('http://engine.io');
expect(res.header['access-control-allow-origin']).to.be('*');
expect(res.header['access-control-allow-methods']).to.be('GET,HEAD,PUT,PATCH,POST,DELETE');
expect(res.header['access-control-allow-headers']).to.be('origin, content-type, accept');
done();
Expand Down