express-http-proxy
Advanced tools
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
| 'use strict'; | ||
| var assert = require('assert'); | ||
| var express = require('express'); | ||
| var http = require('http'); | ||
| var startProxyTarget = require('./support/proxyTarget'); | ||
| var proxy = require('../'); | ||
| function fakeProxyServer({path, port, response}) { | ||
| var proxyRouteFn = [{ | ||
| method: 'get', | ||
| path: path, | ||
| fn: function (req, res) { | ||
| res.write(response); | ||
| res.end(); | ||
| } | ||
| }]; | ||
| return startProxyTarget(port, 1000, proxyRouteFn); | ||
| } | ||
| function simulateUserRequest() { | ||
| return new Promise(function (resolve, reject) { | ||
| var req = http.request({ hostname: 'localhost', port: 8308, path: '/' }, function (res) { | ||
| var chunks = []; | ||
| res.on('data', function (chunk) { chunks.push(chunk.toString()); }); | ||
| res.on('end', function () { resolve(chunks); }); | ||
| }); | ||
| req.on('error', function (e) { | ||
| reject('problem with request:', e.message); | ||
| }); | ||
| req.end(); | ||
| }) | ||
| } | ||
| describe('handle multiple proxies in the same runtime', function () { | ||
| this.timeout(3000); | ||
| var server; | ||
| var targetServer, targetServer2; | ||
| beforeEach(function () { | ||
| targetServer = fakeProxyServer({path:'/', port: '8309', response: '8309_response'}); | ||
| targetServer2 = fakeProxyServer({path: '/', port: '8310', response: '8310_response'}); | ||
| }); | ||
| afterEach(function () { | ||
| server.close(); | ||
| targetServer.close(); | ||
| targetServer2.close(); | ||
| }); | ||
| describe("When two distinct proxies are defined for the global route", () => { | ||
| afterEach(() => server.close()) | ||
| it('the first proxy definition should be used if it succeeds', function (done) { | ||
| var app = express(); | ||
| app.use(proxy('http://localhost:8309', {})); | ||
| app.use(proxy('http://localhost:8310', {})); | ||
| server = app.listen(8308) | ||
| simulateUserRequest() | ||
| .then(function (res) { | ||
| assert.equal(res[0], '8309_response'); | ||
| done(); | ||
| }) | ||
| .catch(done); | ||
| }); | ||
| it('the fall through definition should be used if the prior skipsToNext', function (done) { | ||
| var app = express(); | ||
| app.use(proxy('http://localhost:8309', { | ||
| skipToNextHandlerFilter: () => { return true } // no matter what, reject this proxy request, and call next() | ||
| })); | ||
| app.use(proxy('http://localhost:8310')) | ||
| server = app.listen(8308) | ||
| simulateUserRequest() | ||
| .then(function (res) { | ||
| assert.equal(res[0], '8310_response'); | ||
| done(); | ||
| }) | ||
| .catch(done); | ||
| }); | ||
| }) | ||
| }); |
+1
-1
@@ -43,3 +43,3 @@ { | ||
| 1, | ||
| 3 | ||
| 4 | ||
| ], | ||
@@ -46,0 +46,0 @@ "complexity": [ |
@@ -13,2 +13,3 @@ 'use strict'; | ||
| var parseBody = (!options.parseReqBody) ? Promise.resolve(null) : requestOptions.bodyContent(req, res, options); | ||
| var createReqOptions = requestOptions.create(req, res, options, host); | ||
@@ -19,2 +20,3 @@ | ||
| .then(function (responseArray) { | ||
| req.body = responseArray[0]; | ||
| Container.proxy.bodyContent = responseArray[0]; | ||
@@ -24,2 +26,6 @@ Container.proxy.reqBuilder = responseArray[1]; | ||
| return Container; | ||
| }) | ||
| .catch(function (err) { | ||
| debug('error occurred while building proxy request:', err); | ||
| return Promise.reject(err); | ||
| }); | ||
@@ -26,0 +32,0 @@ } |
@@ -14,4 +14,3 @@ 'use strict'; | ||
| if (shouldSkipToNext) { | ||
| container.user.res.expressHttpProxy = container.proxy; | ||
| return Promise.reject(container.user.next()); | ||
| return Promise.reject(); | ||
| } else { | ||
@@ -18,0 +17,0 @@ return Promise.resolve(container); |
@@ -39,18 +39,13 @@ 'use strict'; | ||
| // this guy should go elsewhere, down the chain | ||
| if (options.parseReqBody) { | ||
| // We are parsing the body ourselves so we need to write the body content | ||
| // and then manually end the request. | ||
| // We are parsing the body ourselves so we need to write the body content | ||
| // and then manually end the request. | ||
| //if (bodyContent instanceof Object) { | ||
| //throw new Error | ||
| //debugger; | ||
| //bodyContent = JSON.stringify(bodyContent); | ||
| //} | ||
| if (bodyContent.length) { | ||
| var body = bodyContent; | ||
| var contentType = proxyReq.getHeader('Content-Type'); | ||
| if (contentType === 'x-www-form-urlencoded' || contentType === 'application/x-www-form-urlencoded') { | ||
| // contentTypes may contain semi-colon | ||
| // example: "application/x-www-form-urlencoded; charset=UTF-8" | ||
| if (contentType && contentType.match('x-www-form-urlencoded')) { | ||
| try { | ||
@@ -67,2 +62,5 @@ var params = JSON.parse(body); | ||
| proxyReq.end(); | ||
| } else if (bodyContent) { | ||
| proxyReq.write(bodyContent); | ||
| proxyReq.end(); | ||
| } else { | ||
@@ -69,0 +67,0 @@ // Pipe will call end when it has completely read from the request. |
+5
-4
@@ -47,5 +47,2 @@ 'use strict'; | ||
| .catch(function (err) { | ||
| // I sometimes reject without an error to shortcircuit the remaining | ||
| // steps and return control to the host application. | ||
| if (err) { | ||
@@ -57,3 +54,7 @@ var resolver = (container.options.proxyErrorHandler) ? | ||
| } else { | ||
| next(); | ||
| // I sometimes reject without an error to shortcircuit the remaining | ||
| // steps -- e.g. in maybeSkipToNextHandler -- and return control to | ||
| // the host application for continuing on without raising an error. | ||
| return next(); | ||
| } | ||
@@ -60,0 +61,0 @@ }); |
+2
-2
@@ -13,5 +13,5 @@ 'use strict'; | ||
| } else if (typeof body === 'object') { | ||
| ret = new Buffer(JSON.stringify(body), options.reqBodyEncoding); | ||
| ret = Buffer.from(JSON.stringify(body), options.reqBodyEncoding); | ||
| } else if (typeof body === 'string') { | ||
| ret = new Buffer(body, options.reqBodyEncoding); | ||
| ret = Buffer.from(body, options.reqBodyEncoding); | ||
| } | ||
@@ -18,0 +18,0 @@ return ret; |
@@ -93,4 +93,9 @@ 'use strict'; | ||
| return Promise.resolve(req.body); | ||
| } else if (!req.readable) { | ||
| return Promise.reject( | ||
| 'Tried to parse body after request body has already been read.' + | ||
| ' Try setting parseReqBody to false and manually specify the body you want to send in decorateProxyReqBody.' | ||
| ); | ||
| } else { | ||
| // Returns a promise if no callback specified and global Promise exists. | ||
| // Returns a promise | ||
@@ -97,0 +102,0 @@ return getRawBody(req, { |
+2
-2
| { | ||
| "name": "express-http-proxy", | ||
| "version": "2.0.0", | ||
| "version": "2.1.0", | ||
| "description": "http proxy middleware for express", | ||
@@ -11,3 +11,3 @@ "engines": { | ||
| "test": "npm -s run mocha && npm run -s lint", | ||
| "test:debug": "mocha debug -R spec test --recursive --exit", | ||
| "test:debug": "mocha inspect --debug-brk -R spec test --recursive --exit", | ||
| "mocha": "mocha -R spec test --recursive --exit", | ||
@@ -14,0 +14,0 @@ "lint": "eslint index.js app/**/*js lib/*js" |
+24
-3
@@ -76,2 +76,7 @@ # express-http-proxy [](http://badge.fury.io/js/express-http-proxy) [](https://travis-ci.org/villadora/express-http-proxy) | ||
| ``` | ||
| Notie: Host is only the host name. Any params after in url will be ignored. For ``http://google.com/myPath`, ``myPath`` will be ignored because the host name is ``google.com``. | ||
| See ``proxyReqPathResolver`` for more detailed path information. | ||
| ### Middleware mixing | ||
@@ -81,6 +86,5 @@ | ||
| ``` | ||
| ```js | ||
| app.use('/proxy', proxy('http://foo.bar.com')) | ||
| app.use('/proxy', 'http://foo.bar.com') | ||
| // Declare use of body-parser AFTER the use of proxy | ||
@@ -91,2 +95,15 @@ app.use(bodyParser.foo(bar)) | ||
| If this cannot be avoided and you MUST proxy after `body-parser` has been registered, set `parseReqBody` to `false` and explicitly specify the body you wish to send in `proxyReqBodyDecorator`. | ||
| ```js | ||
| app.use(bodyParser.foo(bar)) | ||
| app.use('/proxy', proxy('http://foo.bar.com', { | ||
| parseReqBody: false, | ||
| proxyReqBodyDecorator: function () { | ||
| }, | ||
| })) | ||
| ``` | ||
| ### Options | ||
@@ -581,2 +598,6 @@ | ||
| | --- | --- | | ||
| | 2.1.0 | * Fixes => content-types can have semi-colons, and we need to parse around this.<br /> | ||
| * Improves => using proxyReqBodyDecorator with parseReqBody=false. <br /> | ||
| * Repairs => Can't use proxy() twice in Express middleware stack. <br /> | ||
| * Fixes => Instead of new Buffer using Buffer.from as per https://nodejs.org/api/buffer.html\#buffer_new_buffer_string_encoding. <br /> | ||
| | 2.0.0 | Update all dependencies; set stage for next iteration. `express-http-proxy` interface has not changed, but the underlying libraries are not guaranteed to be backward compatible. Versions beyond this point are expected to be run in node verions >= 16. | | ||
@@ -583,0 +604,0 @@ | ----- | ----------------------------------------------------------------------- | |
+92
-0
@@ -158,2 +158,94 @@ 'use strict'; | ||
| it('should use proxyReqBodyDecorator with parseReqBody=false', function (done) { | ||
| var scope = nock('http://127.0.0.1:12345') | ||
| .get('/', {}) | ||
| .matchHeader('Content-Type', 'application/json') | ||
| .reply(200, { | ||
| name: 'proxyReqBodyDecorator + parseReqBody=false works' | ||
| }); | ||
| var payload = {}; | ||
| localServer.use('/proxy', proxy('http://127.0.0.1:12345', { | ||
| parseReqBody: false, | ||
| proxyReqBodyDecorator: () => JSON.stringify(payload), | ||
| })); | ||
| request(localServer) | ||
| .get('/proxy') | ||
| .send(payload) | ||
| .set('Content-Type', 'application/json') | ||
| .expect(function (res) { | ||
| assert(res.body.name === 'proxyReqBodyDecorator + parseReqBody=false works'); | ||
| scope.done(); | ||
| }) | ||
| .end(done); | ||
| }); | ||
| describe('when body-parser.json() is using strict=false', function () { | ||
| beforeEach(function () { | ||
| localServer = createLocalApplicationServer(); | ||
| localServer.use(bodyParser.json({ strict: false })); | ||
| }); | ||
| var testCases = [ | ||
| { value: false }, | ||
| { value: null }, | ||
| { value: '' }, | ||
| ]; | ||
| testCases.forEach(function (test) { | ||
| var valueString = JSON.stringify(test.value); | ||
| it('errors when body is ' + valueString, function (done) { | ||
| localServer.use('/proxy', proxy('http://127.0.0.1:12345')); | ||
| localServer.use(function (err, req, res, next) { res.send(err); next(); }); | ||
| request(localServer) | ||
| .get('/proxy') | ||
| .send(valueString) | ||
| .set('Content-Type', 'application/json') | ||
| .expect(function (res) { | ||
| assert( | ||
| res.text === ( | ||
| 'Tried to parse body after request body has already been read.' + | ||
| ' Try setting parseReqBody to false and manually specify the body' + | ||
| ' you want to send in decorateProxyReqBody.' | ||
| ) | ||
| ); | ||
| }) | ||
| .end(done); | ||
| }); | ||
| it( | ||
| 'succeeds when parseReqBody=false and proxyReqBodyDecorator explicitly returns ' + valueString, | ||
| function (done) { | ||
| var scope = nock('http://127.0.0.1:12345') | ||
| .get('/', valueString) | ||
| .matchHeader('Content-Type', 'application/json') | ||
| .reply(200, valueString, { | ||
| 'Content-Type': 'application/json', | ||
| }); | ||
| localServer.use('/proxy', proxy('http://127.0.0.1:12345', { | ||
| parseReqBody: false, | ||
| proxyReqBodyDecorator: function () { | ||
| return valueString; | ||
| }, | ||
| })); | ||
| request(localServer) | ||
| .get('/proxy') | ||
| .send(valueString) | ||
| .set('Content-Type', 'application/json') | ||
| .expect(function (res) { | ||
| assert(res.body === test.value); | ||
| scope.done(); | ||
| }) | ||
| .end(done); | ||
| } | ||
| ); | ||
| }); | ||
| }); | ||
| }); |
@@ -20,3 +20,3 @@ 'use strict'; | ||
| slowTarget = express(); | ||
| slowTarget.use(function (req, res) { res.sendStatus(404); }); | ||
| slowTarget.use(function (req, res) { res.sendStatus(407); }); | ||
| serverReference = slowTarget.listen(12345); | ||
@@ -30,4 +30,4 @@ }); | ||
| var OUTCOMES = [ | ||
| { shouldSkip: true, expectedStatus: 200 }, | ||
| { shouldSkip: false, expectedStatus: 404 } | ||
| { shouldSkip: false, expectedStatus: 407 }, | ||
| { shouldSkip: true, expectedStatus: 203 }, | ||
| ]; | ||
@@ -46,6 +46,3 @@ | ||
| app.use(function (req, res) { | ||
| assert(res.expressHttpProxy instanceof Object); | ||
| assert(res.expressHttpProxy.res instanceof http.IncomingMessage); | ||
| assert(res.expressHttpProxy.req instanceof Object); | ||
| res.sendStatus(200); | ||
| res.sendStatus(203); | ||
| }); | ||
@@ -52,0 +49,0 @@ |
+92
-0
@@ -131,2 +131,94 @@ 'use strict'; | ||
| it('should use proxyReqBodyDecorator with parseReqBody=false', function (done) { | ||
| var scope = nock('http://127.0.0.1:12345') | ||
| .post('/', {}) | ||
| .matchHeader('Content-Type', 'application/json') | ||
| .reply(200, { | ||
| name: 'proxyReqBodyDecorator + parseReqBody=false works' | ||
| }); | ||
| var payload = {}; | ||
| localServer.use('/proxy', proxy('http://127.0.0.1:12345', { | ||
| parseReqBody: false, | ||
| proxyReqBodyDecorator: () => JSON.stringify(payload), | ||
| })); | ||
| request(localServer) | ||
| .post('/proxy') | ||
| .send(payload) | ||
| .set('Content-Type', 'application/json') | ||
| .expect(function (res) { | ||
| assert(res.body.name === 'proxyReqBodyDecorator + parseReqBody=false works'); | ||
| scope.done(); | ||
| }) | ||
| .end(done); | ||
| }); | ||
| describe('when body-parser.json() is using strict=false', function () { | ||
| beforeEach(function () { | ||
| localServer = createLocalApplicationServer(); | ||
| localServer.use(bodyParser.json({ strict: false })); | ||
| }); | ||
| var testCases = [ | ||
| { value: false }, | ||
| { value: null }, | ||
| { value: '' }, | ||
| ]; | ||
| testCases.forEach(function (test) { | ||
| var valueString = JSON.stringify(test.value); | ||
| it('errors when body is ' + valueString, function (done) { | ||
| localServer.use('/proxy', proxy('http://127.0.0.1:12345')); | ||
| localServer.use(function (err, req, res, next) { res.send(err); next(); }); | ||
| request(localServer) | ||
| .post('/proxy') | ||
| .send(valueString) | ||
| .set('Content-Type', 'application/json') | ||
| .expect(function (res) { | ||
| assert( | ||
| res.text === ( | ||
| 'Tried to parse body after request body has already been read.' + | ||
| ' Try setting parseReqBody to false and manually specify the body' + | ||
| ' you want to send in decorateProxyReqBody.' | ||
| ) | ||
| ); | ||
| }) | ||
| .end(done); | ||
| }); | ||
| it( | ||
| 'succeeds when parseReqBody=false and proxyReqBodyDecorator explicitly returns ' + valueString, | ||
| function (done) { | ||
| var scope = nock('http://127.0.0.1:12345') | ||
| .post('/', valueString) | ||
| .matchHeader('Content-Type', 'application/json') | ||
| .reply(200, valueString, { | ||
| 'Content-Type': 'application/json', | ||
| }); | ||
| localServer.use('/proxy', proxy('http://127.0.0.1:12345', { | ||
| parseReqBody: false, | ||
| proxyReqBodyDecorator: function () { | ||
| return valueString; | ||
| }, | ||
| })); | ||
| request(localServer) | ||
| .post('/proxy') | ||
| .send(valueString) | ||
| .set('Content-Type', 'application/json') | ||
| .expect(function (res) { | ||
| assert(res.body === test.value); | ||
| scope.done(); | ||
| }) | ||
| .end(done); | ||
| } | ||
| ); | ||
| }); | ||
| }); | ||
| }); |
@@ -68,2 +68,3 @@ 'use strict'; | ||
| reqOpt.headers['user-agent'] = 'test user agent'; | ||
| reqOpt.headers['content-type'] = 'multipart/form-data'; | ||
| assert(req instanceof http.IncomingMessage); | ||
@@ -79,2 +80,3 @@ return reqOpt; | ||
| assert.equal(res.body.headers['user-agent'], 'test user agent'); | ||
| assert.equal(res.body.headers['content-type'], 'multipart/form-data'); | ||
| done(); | ||
@@ -81,0 +83,0 @@ }); |
Network access
Supply chain riskThis module accesses the network.
Found 2 instances in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 2 instances in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
136925
18%62
5.08%3000
8.74%634
3.43%8
14.29%