From 8a24a1e18f384d29a125eda1d2311bdd8ec66871 Mon Sep 17 00:00:00 2001 From: Mike Pennisi Date: Mon, 24 Nov 2014 17:14:48 -0500 Subject: [PATCH] Set `Content-Length` header for OPTIONS requests Web browsers automatically issue an OPTIONS request in advance of other HTTP requests when the document's domain does not match the target in order to facilitate Cross-Origin Resource Sharing. These requests are forbidden from specifying a body and typically do not specify an (unecessary) `Length` header. Node.js automatically adds the `Content-Encoding: chunked` header value to requests that do not specify a `Length` header. This makes proxied OPTIONS requests from web browsers invalid. Explicitly set the `Content-Length` header of all `OPTIONS` requests to "0", disabling the default "chunked" encoding behavior [2]. [1] http://www.w3.org/TR/cors/ [2] http://nodejs.org/api/http.html --- lib/http-proxy/passes/web-incoming.js | 3 ++- test/lib-http-proxy-passes-web-incoming-test.js | 13 +++++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/lib/http-proxy/passes/web-incoming.js b/lib/http-proxy/passes/web-incoming.js index 572c11a8c..369171eb4 100644 --- a/lib/http-proxy/passes/web-incoming.js +++ b/lib/http-proxy/passes/web-incoming.js @@ -29,7 +29,8 @@ web_o = Object.keys(web_o).map(function(pass) { */ function deleteLength(req, res, options) { - if(req.method === 'DELETE' && !req.headers['content-length']) { + if((req.method === 'DELETE' || req.method === 'OPTIONS') + && !req.headers['content-length']) { req.headers['content-length'] = '0'; } }, diff --git a/test/lib-http-proxy-passes-web-incoming-test.js b/test/lib-http-proxy-passes-web-incoming-test.js index f70001035..f2c6f1304 100644 --- a/test/lib-http-proxy-passes-web-incoming-test.js +++ b/test/lib-http-proxy-passes-web-incoming-test.js @@ -5,14 +5,23 @@ var webPasses = require('../lib/http-proxy/passes/web-incoming'), describe('lib/http-proxy/passes/web.js', function() { describe('#deleteLength', function() { - it('should change `content-length`', function() { + it('should change `content-length` for DELETE requests', function() { var stubRequest = { method: 'DELETE', headers: {} }; webPasses.deleteLength(stubRequest, {}, {}); expect(stubRequest.headers['content-length']).to.eql('0'); - }) + }); + + it('should change `content-length` for OPTIONS requests', function() { + var stubRequest = { + method: 'OPTIONS', + headers: {} + }; + webPasses.deleteLength(stubRequest, {}, {}); + expect(stubRequest.headers['content-length']).to.eql('0'); + }); }); describe('#timeout', function() {