Skip to content

Commit

Permalink
[feat] Add an option to toggle handling of OPTIONS requests (#491)
Browse files Browse the repository at this point in the history
By setting `handlePreflightRequest` to false, OPTIONS request are no
longer processed by engine.io. A function can also be provided.
  • Loading branch information
darrachequesne committed Mar 11, 2017
1 parent 0946596 commit 81ef0bc
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 1 deletion.
1 change: 1 addition & 0 deletions README.md
Expand Up @@ -255,6 +255,7 @@ to a single process.
- `path` (`String`): name of the path to capture (`/engine.io`).
- `destroyUpgrade` (`Boolean`): destroy unhandled upgrade requests (`true`)
- `destroyUpgradeTimeout` (`Number`): milliseconds after which unhandled requests are ended (`1000`)
- `handlePreflightRequest` (`Boolean|Function`): whether to let engine.io handle the OPTIONS requests. You can also pass a custom function to handle the requests (`true`)
- `generateId`
- Generate a socket id.
- Overwrite this method to generate your custom socket id.
Expand Down
9 changes: 8 additions & 1 deletion lib/server.js
Expand Up @@ -446,6 +446,9 @@ Server.prototype.attach = function (server, options) {
path += '/';

function check (req) {
if ('OPTIONS' === req.method && false === options.handlePreflightRequest) {
return false;
}
return path === req.url.substr(0, path.length);
}

Expand All @@ -459,7 +462,11 @@ Server.prototype.attach = function (server, options) {
server.on('request', function (req, res) {
if (check(req)) {
debug('intercepting request for path "%s"', path);
self.handleRequest(req, res);
if ('OPTIONS' === req.method && 'function' === typeof options.handlePreflightRequest) {
options.handlePreflightRequest.call(server, req, res);
} else {
self.handleRequest(req, res);
}
} else {
for (var i = 0, l = listeners.length; i < l; i++) {
listeners[i].call(server, req, res);
Expand Down
61 changes: 61 additions & 0 deletions test/server.js
Expand Up @@ -2542,6 +2542,67 @@ describe('server', function () {
});
});

describe('cors', function () {
it('should handle OPTIONS requests', function (done) {
listen({handlePreflightRequest: true}, function (port) {
request.options('http://localhost:%d/engine.io/default/'.s(port))
.set('Origin', 'http://engine.io')
.query({ transport: 'polling' })
.end(function (res) {
expect(res.status).to.be(400);
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');
done();
});
});
});

it('should not handle OPTIONS requests', function (done) {
listen({handlePreflightRequest: false}, function (port) {
request.options('http://localhost:%d/engine.io/default/'.s(port))
.set('Origin', 'http://engine.io')
.query({ transport: 'polling' })
.end(function (res) {
expect(res.status).to.be(501);
expect(res.body.code).to.be(undefined);
done();
});
});
});

it('should handle OPTIONS requests with the given function', function (done) {
var handlePreflightRequest = function (req, res) {
var headers = {};
if (req.headers.origin) {
headers['Access-Control-Allow-Credentials'] = 'true';
headers['Access-Control-Allow-Origin'] = req.headers.origin;
} else {
headers['Access-Control-Allow-Origin'] = '*';
}
headers['Access-Control-Allow-Methods'] = 'GET,HEAD,PUT,PATCH,POST,DELETE';
headers['Access-Control-Allow-Headers'] = 'origin, content-type, accept';
res.writeHead(200, headers);
res.end();
};
listen({handlePreflightRequest: handlePreflightRequest}, function (port) {
request.options('http://localhost:%d/engine.io/default/'.s(port))
.set('Origin', 'http://engine.io')
.query({ transport: 'polling' })
.end(function (res) {
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-methods']).to.be('GET,HEAD,PUT,PATCH,POST,DELETE');
expect(res.header['access-control-allow-headers']).to.be('origin, content-type, accept');
done();
});
});
});
});

if (!UWS_ENGINE && parseInt(process.versions.node, 10) >= 4) {
describe('wsEngine option', function () {
it('should allow loading of other websocket server implementation like uws', function (done) {
Expand Down

0 comments on commit 81ef0bc

Please sign in to comment.