From c6b8f6b13e71c656ad45a03895eb8dff46bbd6af Mon Sep 17 00:00:00 2001 From: Liran Brimer Date: Thu, 12 Dec 2019 13:17:37 +0200 Subject: [PATCH 1/5] feat: async router --- src/http-proxy-middleware.ts | 14 +++++++------- src/router.ts | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/http-proxy-middleware.ts b/src/http-proxy-middleware.ts index 342e9da2..421ac9a9 100644 --- a/src/http-proxy-middleware.ts +++ b/src/http-proxy-middleware.ts @@ -47,7 +47,7 @@ export class HttpProxyMiddleware { // https://github.com/Microsoft/TypeScript/wiki/'this'-in-TypeScript#red-flags-for-this public middleware = async (req, res, next) => { if (this.shouldProxy(this.config.context, req)) { - const activeProxyOptions = this.prepareProxyRequest(req); + const activeProxyOptions = await this.prepareProxyRequest(req); this.proxy.web(req, res, activeProxyOptions); } else { next(); @@ -68,9 +68,9 @@ export class HttpProxyMiddleware { } }; - private handleUpgrade = (req, socket, head) => { + private handleUpgrade = async (req, socket, head) => { if (this.shouldProxy(this.config.context, req)) { - const activeProxyOptions = this.prepareProxyRequest(req); + const activeProxyOptions = await this.prepareProxyRequest(req); this.proxy.ws(req, socket, head, activeProxyOptions); this.logger.info('[HPM] Upgrading to WebSocket'); } @@ -97,7 +97,7 @@ export class HttpProxyMiddleware { * @param {Object} req * @return {Object} proxy options */ - private prepareProxyRequest = req => { + private prepareProxyRequest = async (req) => { // https://github.com/chimurai/http-proxy-middleware/issues/17 // https://github.com/chimurai/http-proxy-middleware/issues/94 req.url = req.originalUrl || req.url; @@ -109,7 +109,7 @@ export class HttpProxyMiddleware { // Apply in order: // 1. option.router // 2. option.pathRewrite - this.applyRouter(req, newProxyOptions); + await this.applyRouter(req, newProxyOptions); this.applyPathRewrite(req, this.pathRewriter); // debug logging for both http(s) and websockets @@ -133,11 +133,11 @@ export class HttpProxyMiddleware { }; // Modify option.target when router present. - private applyRouter = (req, options) => { + private applyRouter = async (req, options) => { let newTarget; if (options.router) { - newTarget = Router.getTarget(req, options); + newTarget = await Router.getTarget(req, options); if (newTarget) { this.logger.debug( diff --git a/src/router.ts b/src/router.ts index 0e24a2e4..37200b94 100644 --- a/src/router.ts +++ b/src/router.ts @@ -2,14 +2,14 @@ import * as _ from 'lodash'; import { getInstance } from './logger'; const logger = getInstance(); -export function getTarget(req, config) { +export async function getTarget(req, config) { let newTarget; const router = config.router; if (_.isPlainObject(router)) { newTarget = getTargetFromProxyTable(req, router); } else if (_.isFunction(router)) { - newTarget = router(req); + newTarget = await router(req); } return newTarget; From 7c3f9c192d211011166ced20d3212b911043194b Mon Sep 17 00:00:00 2001 From: Liran Brimer Date: Thu, 12 Dec 2019 13:35:25 +0200 Subject: [PATCH 2/5] fix: lint --- src/http-proxy-middleware.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/http-proxy-middleware.ts b/src/http-proxy-middleware.ts index 421ac9a9..f3f6634f 100644 --- a/src/http-proxy-middleware.ts +++ b/src/http-proxy-middleware.ts @@ -97,7 +97,7 @@ export class HttpProxyMiddleware { * @param {Object} req * @return {Object} proxy options */ - private prepareProxyRequest = async (req) => { + private prepareProxyRequest = async req => { // https://github.com/chimurai/http-proxy-middleware/issues/17 // https://github.com/chimurai/http-proxy-middleware/issues/94 req.url = req.originalUrl || req.url; From 37f4e80e7c09ddc8f9771db910fbe676c73b57a2 Mon Sep 17 00:00:00 2001 From: Liran Brimer Date: Mon, 16 Dec 2019 11:46:25 +0200 Subject: [PATCH 3/5] fix: tests to expect promise from GetTarget --- test/unit/router.spec.ts | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/test/unit/router.spec.ts b/test/unit/router.spec.ts index 06f44e40..70b0b3cc 100644 --- a/test/unit/router.spec.ts +++ b/test/unit/router.spec.ts @@ -40,7 +40,7 @@ describe('router unit test', () => { expect(request.url).toBe('/'); }); it('should return new target', () => { - expect(result).toBe('http://foobar.com:666'); + expect(result).resolves.toBe('http://foobar.com:666'); }); }); }); @@ -64,7 +64,7 @@ describe('router unit test', () => { describe('without router config', () => { it('should return the normal target when router not present in config', () => { result = getTarget(fakeReq, config); - expect(result).toBeUndefined(); + expect(result).resolves.toBeUndefined(); }); }); @@ -72,13 +72,13 @@ describe('router unit test', () => { it('should target http://localhost:6001 when for router:"alpha.localhost"', () => { fakeReq.headers.host = 'alpha.localhost'; result = getTarget(fakeReq, proxyOptionWithRouter); - expect(result).toBe('http://localhost:6001'); + expect(result).resolves.toBe('http://localhost:6001'); }); it('should target http://localhost:6002 when for router:"beta.localhost"', () => { fakeReq.headers.host = 'beta.localhost'; result = getTarget(fakeReq, proxyOptionWithRouter); - expect(result).toBe('http://localhost:6002'); + expect(result).resolves.toBe('http://localhost:6002'); }); }); @@ -86,21 +86,21 @@ describe('router unit test', () => { it('should target http://localhost:6004 without path', () => { fakeReq.headers.host = 'gamma.localhost'; result = getTarget(fakeReq, proxyOptionWithRouter); - expect(result).toBe('http://localhost:6004'); + expect(result).resolves.toBe('http://localhost:6004'); }); it('should target http://localhost:6003 exact path match', () => { fakeReq.headers.host = 'gamma.localhost'; fakeReq.url = '/api'; result = getTarget(fakeReq, proxyOptionWithRouter); - expect(result).toBe('http://localhost:6003'); + expect(result).resolves.toBe('http://localhost:6003'); }); it('should target http://localhost:6004 when contains path', () => { fakeReq.headers.host = 'gamma.localhost'; fakeReq.url = '/api/books/123'; result = getTarget(fakeReq, proxyOptionWithRouter); - expect(result).toBe('http://localhost:6003'); + expect(result).resolves.toBe('http://localhost:6003'); }); }); @@ -108,19 +108,19 @@ describe('router unit test', () => { it('should target http://localhost:6005 with just a path as router config', () => { fakeReq.url = '/rest'; result = getTarget(fakeReq, proxyOptionWithRouter); - expect(result).toBe('http://localhost:6005'); + expect(result).resolves.toBe('http://localhost:6005'); }); it('should target http://localhost:6005 with just a path as router config', () => { fakeReq.url = '/rest/deep/path'; result = getTarget(fakeReq, proxyOptionWithRouter); - expect(result).toBe('http://localhost:6005'); + expect(result).resolves.toBe('http://localhost:6005'); }); it('should target http://localhost:6000 path in not present in router config', () => { fakeReq.url = '/unknow-path'; result = getTarget(fakeReq, proxyOptionWithRouter); - expect(result).toBeUndefined(); + expect(result).resolves.toBeUndefined(); }); }); @@ -128,7 +128,7 @@ describe('router unit test', () => { it('should return first matching target when similar paths are configured', () => { fakeReq.url = '/some/specific/path'; result = getTarget(fakeReq, proxyOptionWithRouter); - expect(result).toBe('http://localhost:6006'); + expect(result).resolves.toBe('http://localhost:6006'); }); }); }); From 33ebf4aacf1b23fc76e94f2954fa2f7d210f1b9c Mon Sep 17 00:00:00 2001 From: Liran Brimer Date: Mon, 16 Dec 2019 11:48:02 +0200 Subject: [PATCH 4/5] tests: async function --- test/unit/router.spec.ts | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/test/unit/router.spec.ts b/test/unit/router.spec.ts index 70b0b3cc..8cad56b9 100644 --- a/test/unit/router.spec.ts +++ b/test/unit/router.spec.ts @@ -45,6 +45,32 @@ describe('router unit test', () => { }); }); + describe('router.getTarget from async function', () => { + let request; + + beforeEach(() => { + proxyOptionWithRouter = { + target: 'http://localhost:6000', + async router(req) { + request = req; + return 'http://foobar.com:666'; + } + }; + + result = getTarget(fakeReq, proxyOptionWithRouter); + }); + + describe('custom dynamic router async function', () => { + it('should provide the request object for dynamic routing', () => { + expect(request.headers.host).toBe('localhost'); + expect(request.url).toBe('/'); + }); + it('should return new target', () => { + expect(result).resolves.toBe('http://foobar.com:666'); + }); + }); + }); + describe('router.getTarget from table', () => { beforeEach(() => { proxyOptionWithRouter = { From 11de79f27a232706a8eba34372a224a1750413af Mon Sep 17 00:00:00 2001 From: Liran Brimer Date: Tue, 24 Dec 2019 09:57:55 +0200 Subject: [PATCH 5/5] doc: README example --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 35507eb9..945802a5 100644 --- a/README.md +++ b/README.md @@ -217,6 +217,12 @@ Providing an alternative way to decide which requests should be proxied; In case router: function(req) { return 'http://localhost:8004'; } + + // Asynchronous router function which returns promise + router: async function(req) { + const url = await doSomeIO(); + return url; + } ``` - **option.logLevel**: string, ['debug', 'info', 'warn', 'error', 'silent']. Default: `'info'`