diff --git a/.gitignore b/.gitignore index 62f54ae..902a7aa 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,5 @@ node_modules coverage/ coverage.lcov -.nyc_output/ \ No newline at end of file +.nyc_output/ +tmp/ diff --git a/test/bodyEncoding.js b/test/bodyEncoding.js deleted file mode 100644 index 9bc1d10..0000000 --- a/test/bodyEncoding.js +++ /dev/null @@ -1,161 +0,0 @@ -'use strict'; -var assert = require('assert'); -var express = require('express'); -var request = require('supertest'); -var fs = require('fs'); -var os = require('os'); -var proxy = require('../'); -var startProxyTarget = require('./support/proxyTarget'); -var TIMEOUT = require('./constants'); - - -describe('body encoding', function () { - var server; - - before(function () { - server = startProxyTarget(8109, 1000); - }); - - after(function () { - server.close(); - }); - - this.timeout(TIMEOUT.STANDARD); - - var pngHex = '89504e470d0a1a0a0' + - '000000d4948445200' + - '00000100000001080' + - '60000001f15c48900' + - '00000a49444154789' + - 'c6300010000050001' + - '0d0a2db4000000004' + - '9454e44ae426082'; - var pngData = new Buffer(pngHex, 'hex'); - - it('allow raw data', function (done) { - var filename = os.tmpdir() + '/express-http-proxy-test-' + (new Date()).getTime() + '-png-transparent.png'; - var app = express(); - - app.use(proxy('localhost:8109', { - reqBodyEncoding: null, - proxyReqBodyDecorator: function (bodyContent) { - assert((new Buffer(bodyContent).toString('hex')).indexOf(pngData.toString('hex')) >= 0, - 'body should contain same data'); - return bodyContent; - } - })); - - fs.writeFile(filename, pngData, function (err) { - if (err) { throw err; } - request(app) - .post('/post') - .attach('image', filename) - .end(function (err) { - fs.unlinkSync(filename); - // This test is both broken and I think unnecessary. - // Its broken because http.bin no longer supports /post, but this test assertion is based on the old - // httpbin behavior. - // The assertion in the decorateRequest above verifies the test title. - //var response = new Buffer(res.body.attachment.data).toString('base64'); - //assert(response.indexOf(pngData.toString('base64')) >= 0, 'response should include original raw data'); - - done(err); - }); - }); - - }); - - describe('when user sets parseReqBody', function () { - it('should not parse body', function (done) { - var filename = os.tmpdir() + '/express-http-proxy-test-' + (new Date()).getTime() + '-png-transparent.png'; - var app = express(); - app.use(proxy('localhost:8109', { - parseReqBody: false, - proxyReqBodyDecorator: function (bodyContent) { - assert(!bodyContent, 'body content should not be parsed.'); - return bodyContent; - } - })); - - fs.writeFile(filename, pngData, function (err) { - if (err) { throw err; } - request(app) - .post('/post') - .attach('image', filename) - .end(function (err) { - fs.unlinkSync(filename); - // This test is both broken and I think unnecessary. - // Its broken because http.bin no longer supports /post, but this test assertion is based on the old - // httpbin behavior. - // The assertion in the decorateRequest above verifies the test title. - // var response = new Buffer(res.body.attachment.data).toString('base64'); - // assert(response.indexOf(pngData.toString('base64')) >= 0, 'response should include original raw data'); - - done(err); - }); - }); - }); - it('should not fail on large limit', function (done) { - var filename = os.tmpdir() + '/express-http-proxy-test-' + (new Date()).getTime() + '-png-transparent.png'; - var app = express(); - app.use(proxy('localhost:8109', { - parseReqBody: false, - limit: '20gb', - })); - fs.writeFile(filename, pngData, function (err) { - if (err) { throw err; } - request(app) - .post('/post') - .attach('image', filename) - .end(function (err) { - fs.unlinkSync(filename); - assert(err === null); - // This test is both broken and I think unnecessary. - // Its broken because http.bin no longer supports /post, but this test assertion is based on the old - // httpbin behavior. - // The assertion in the decorateRequest above verifies the test title. - //var response = new Buffer(res.body.attachment.data).toString('base64'); - //assert(response.indexOf(pngData.toString('base64')) >= 0, 'response should include original raw data'); - - done(err); - }); - }); - }); - it('should fail with an error when exceeding limit', function (done) { - var app = express(); - app.use(proxy('localhost:8109', { - limit: 1, - })); - // silence jshint warning about unused vars - express error handler *needs* 4 args - app.use(function (err, req, res, next) { // eslint-disable-line no-unused-vars - res.json(err); - }); - request(app) - .post('/post') - .send({ some: 'json' }) - .end(function (err, response) { - assert(response.body.message === 'request entity too large'); - done(); - }); - }); - }); - - - describe('when user sets reqBodyEncoding', function () { - it('should set the accepts-charset header', function (done) { - var app = express(); - app.use(proxy('localhost:8109', { - reqBodyEncoding: 'utf-16' - })); - request(app) - .get('/headers') - .end(function (err, res) { - if (err) { throw err; } - assert.equal(res.body.headers['accept-charset'], 'utf-16'); - done(err); - }); - }); - }); - - -}); diff --git a/test/catchingErrors.js b/test/catchingErrors.js index 90aba7a..13d057a 100644 --- a/test/catchingErrors.js +++ b/test/catchingErrors.js @@ -19,8 +19,8 @@ describe('when server responds with an error', function () { app = express(); }); - afterEach(function () { - serverReference.close(); + afterEach(async function () { + await serverReference.close(); }); var STATUS_CODES = [ diff --git a/test/cookies.js b/test/cookies.js index a7c3c48..e1e7caf 100644 --- a/test/cookies.js +++ b/test/cookies.js @@ -11,39 +11,44 @@ var proxyRouteFn = [{ method: 'get', path: '/cookieTest', fn: function (req, res) { - Object.keys(req.cookies).forEach(function (key) { + // This stub proxy server method simply copies the cookies from the inbound + // request to the outbound response. This lets us check the proxy reponse + // for the cookies on the request. + Object.keys(req.cookies).forEach(key => { res.cookie(key, req.cookies[key]); }); res.sendStatus(200); } }]; -describe('proxies cookie', function () { - this.timeout(TIMEOUT.STANDARD); +describe("cookies", () => { + describe('when cookies are sent on the user request', function () { + this.timeout(TIMEOUT.STANDARD); - var app; - var proxyServer; + var app; + var proxyServer; - beforeEach(function () { - proxyServer = proxyTarget(12346, 100, proxyRouteFn); - app = express(); - app.use(proxy('localhost:12346')); - }); + beforeEach(function () { + proxyServer = proxyTarget(12346, 100, proxyRouteFn); + app = express(); + app.use(proxy('localhost:12346')); + }); - afterEach(function () { - proxyServer.close(); - }); + afterEach(function () { + proxyServer.close(); + }); - it('set cookie', function (done) { - request(app) - .get('/cookieTest') - .set('Cookie', 'myApp-token=12345667') - .end(function (err, res) { - var cookiesMatch = res.headers['set-cookie'].filter(function (item) { - return item.match(/myApp-token=12345667/); + it('they are copied to the proxy request', function (done) { + request(app) + .get('/cookieTest') + .set('Cookie', 'myApp-token=12345667') + .end(function (err, res) { + var cookiesMatch = res.headers['set-cookie'].filter(function (item) { + return item.match(/myApp-token=12345667/); + }); + assert(cookiesMatch); + done(err); }); - assert(cookiesMatch); - done(err); - }); + }); }); }); diff --git a/test/proxyReqPathResolver.js b/test/proxyReqPathResolver.js index 7410eb8..e3bdf95 100644 --- a/test/proxyReqPathResolver.js +++ b/test/proxyReqPathResolver.js @@ -15,7 +15,7 @@ describe('resolveProxyReqPath', function () { this.timeout(TIMEOUT.STANDARD); - before(function () { + beforeEach(function () { var handlers = [{ method: 'get', path: '/working', @@ -27,8 +27,8 @@ describe('resolveProxyReqPath', function () { server = proxyTarget(12345, 100, handlers); }); - after(function () { - server.close(); + afterEach(async () => { + await server.close(); }); aliases.forEach(function (alias) { diff --git a/test/rawBodyLimit.js b/test/rawBodyLimit.js new file mode 100644 index 0000000..1ccf799 --- /dev/null +++ b/test/rawBodyLimit.js @@ -0,0 +1,86 @@ +'use strict'; +var getRawBody = require('raw-body'); +var assert = require('assert'); +var express = require('express'); +var request = require('supertest'); +var fs = require('fs'); +var os = require('os'); +var proxy = require('../'); +var startProxyTarget = require('./support/proxyTarget'); +var TIMEOUT = require('./constants'); + +const PORT_NUMBER =8109; + +const pngHex = '89504e470d0a1a0a0' + + '000000d4948445200' + + '00000100000001080' + + '60000001f15c48900' + + '00000a49444154789' + + 'c6300010000050001' + + '0d0a2db4000000004' + + '9454e44ae426082'; +const pngData = Buffer.from(pngHex, 'hex'); + +const processStuff = (req, res, next) => { + getRawBody(req, { + length: req.headers['content-length'], + }).then((rawBody) => { + res.json({rawBody, headers: req.headers}); + }) +} + +describe('limit', function () { + var server; + + beforeEach(function () { + server = startProxyTarget(8109); + }); + + afterEach(async function () { + await server.close(); + }); + + it('should not fail on large limit', function (done) { + var filename = os.tmpdir() + '/express-http-proxy-test-' + (new Date()).getTime() + '-png-transparent.png'; + var app = express(); + app.use(proxy('localhost:8109', { + parseReqBody: false, + limit: '20gb', + })); + fs.writeFile(filename, pngData, function (err) { + if (err) { throw err; } + request(app) + .post('/post') + .attach('image', filename) + .end(function (err) { + fs.unlinkSync(filename); + assert(err === null); + // This test is both broken and I think unnecessary. + // Its broken because http.bin no longer supports /post, but this test assertion is based on the old + // httpbin behavior. + // The assertion in the decorateRequest above verifies the test title. + //var response = new Buffer(res.body.attachment.data).toString('base64'); + //assert(response.indexOf(pngData.toString('base64')) >= 0, 'response should include original raw data'); + + done(err); + }); + }); + }); + it('should fail with an error when exceeding limit', function (done) { + var app = express(); + app.use(proxy('localhost:8109', { + limit: 1, + })); + // silence jshint warning about unused vars - express error handler *needs* 4 args + app.use(function (err, req, res, next) { // eslint-disable-line no-unused-vars + res.json(err); + }); + request(app) + .post('/post') + .send({ some: 'json' }) + .end(function (err, response) { + assert(response.body.message === 'request entity too large'); + done(); + }); + }); +}); diff --git a/test/reqBodyEncoding.js b/test/reqBodyEncoding.js new file mode 100644 index 0000000..7590327 --- /dev/null +++ b/test/reqBodyEncoding.js @@ -0,0 +1,128 @@ +'use strict'; +var getRawBody = require('raw-body'); +var assert = require('assert'); +var express = require('express'); +var request = require('supertest'); +var fs = require('fs'); +var os = require('os'); +var proxy = require('../'); +var startProxyTarget = require('./support/proxyTarget'); +var TIMEOUT = require('./constants'); + +const PORT_NUMBER = 8111; + +const pngHex = '89504e470d0a1a0a0' + + '000000d4948445200' + + '00000100000001080' + + '60000001f15c48900' + + '00000a49444154789' + + 'c6300010000050001' + + '0d0a2db4000000004' + + '9454e44ae426082'; +const pngData = Buffer.from(pngHex, 'hex'); + +const parseRequest = (req, res, next) => { + getRawBody(req, { + length: req.headers['content-length'], + }).then((rawBody) => { + res.json({rawBody, headers: req.headers}); + }) +} + +describe('reqBodyEncoding [controls "accept-charset" header]', function () { + var server; + + beforeEach(() => server = startProxyTarget(8111, 1000, [ + { + method: 'post', + path: '/post', + fn: parseRequest, + } + ])); + afterEach(async () => await server.close()); + + describe('when unset ', () => { + it('sets "accept-charset" to "utf-8"', (done) => { + var app = express(); + app.use(proxy('localhost:8111')); + request(app) + .post('/post') + .end(function (err, res) { + assert(res.body.headers['accept-charset'] === 'utf-8'); + done(err); + }); + }); + }); + + describe('when set to ', () => { + it('leaves "accept-charset" undefined"', (done) => { + var app = express(); + app.use(proxy('localhost:8111', { + reqBodyEncoding: null, + })); + request(app) + .post('/post') + .end(function (err, res) { + assert.equal(res.body.headers['accept-charset'], undefined); + done(err); + }); + }); + describe('specific use cases', () => { + it('image uploads are not set to an encoding', function (done) { + var filename = os.tmpdir() + '/express-http-proxy-test-' + (new Date()).getTime() + '-png-transparent.png'; + var app = express(); + + app.use(proxy('localhost:8111', { + reqBodyEncoding: null, + })); + + fs.writeFile(filename, pngData, function (err) { + if (err) { throw err; } + request(app) + .post('/post') + .attach('image', filename) + .end(function (err, res) { + fs.unlinkSync(filename); + assert(res.body.headers['accept-charset'] === undefined); + assert(res.body.headers['content-type'].match(/multipart\/form-data;/)); + assert(Buffer.from(res.body.rawBody.data).toString('hex').match(pngData.toString('hex'))); + done(err); + }); + }); + + }); + }); + }); + + + describe('when user sets reqBodyEncoding', function () { + describe('when user uses a non-standard accepts-charset header', () => { + it('application uses the non-standard accepts-charset header', (done) => { + var app = express(); + app.use(proxy('localhost:8111', { + reqBodyEncoding: 'utf-jalepeno' + })); + request(app) + .get('/headers') + .end(function (err, res) { + if (err) { throw err; } + assert.equal(res.body.headers['accept-charset'], 'utf-jalepeno'); + done(err); + }); + }); + }); + it('should set the accepts-charset header', function (done) { + var app = express(); + app.use(proxy('localhost:8111', { + reqBodyEncoding: 'utf-16' + })); + request(app) + .get('/headers') + .end(function (err, res) { + if (err) { throw err; } + assert.equal(res.body.headers['accept-charset'], 'utf-16'); + done(err); + }); + }); + }); +}); diff --git a/test/urlParsing.js b/test/urlParsing.js index fd39415..dacb4e2 100644 --- a/test/urlParsing.js +++ b/test/urlParsing.js @@ -7,29 +7,42 @@ var proxy = require('../'); var proxyTarget = require('./support/proxyTarget'); var TIMEOUT = require('./constants'); -describe('url parsing', function () { +describe.only('url parsing', function () { + var server; + + beforeEach(() => server = proxyTarget(8111, 1000, [ + { + method: 'get', + path: '/verify-port', + fn: (req, res, next) => { + debugger; + res.json({recieved: true}); + } + } + ])); + afterEach(async () => await server.close()); this.timeout(TIMEOUT.STANDARD); it('can parse a url with a port', function (done) { var app = express(); - app.use(proxy('http://httpbin.org:80')); + app.use(proxy('http://localhost:8111')); request(app) - .get('/') - .end(function (err) { + .get('/verify-port') + .end(function (err, res) { if (err) { return done(err); } - assert(true); + assert.equal(res.body.recieved, true); done(); }); }); - it('does not throw `Uncaught RangeError` if you have both a port and a trailing slash', function (done) { + it('even with a trailing slash', function (done) { var app = express(); - app.use(proxy('http://httpbin.org:80/')); + app.use(proxy('http://localhost:8111')); request(app) - .get('/') - .end(function (err) { + .get('/verify-port') + .end(function (err, res) { if (err) { return done(err); } - assert(true); + assert.equal(res.body.recieved, true); done(); }); });