http-proxy-middleware 1.0.6 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [v1.1.0](https://github.com/chimurai/http-proxy-middleware/releases/tag/v1.1.0)
4
+
5
+ - fix(errorHandler): fix confusing error message ([#509](https://github.com/chimurai/http-proxy-middleware/pull/509))
6
+ - fix(proxy): close proxy when server closes ([#508](https://github.com/chimurai/http-proxy-middleware/pull/508))
7
+ - refactor(lodash): remove lodash ([#459](https://github.com/chimurai/http-proxy-middleware/pull/459)) ([#507](https://github.com/chimurai/http-proxy-middleware/pull/507)) ([TrySound](https://github.com/TrySound))
8
+ - fix(ETIMEDOUT): return 504 on ETIMEDOUT ([#480](https://github.com/chimurai/http-proxy-middleware/pull/480)) ([aremishevsky](https://github.com/aremishevsky))
9
+
3
10
  ## [v1.0.6](https://github.com/chimurai/http-proxy-middleware/releases/tag/v1.0.6)
4
11
 
5
12
  - chore(deps): lodash 4.17.20 ([#475](https://github.com/chimurai/http-proxy-middleware/pull/475))
package/README.md CHANGED
@@ -540,4 +540,4 @@ $ yarn cover
540
540
 
541
541
  The MIT License (MIT)
542
542
 
543
- Copyright (c) 2015-2020 Steven Chim
543
+ Copyright (c) 2015-2021 Steven Chim
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createConfig = void 0;
4
- const _ = require("lodash");
4
+ const isPlainObj = require("is-plain-obj");
5
5
  const url = require("url");
6
6
  const errors_1 = require("./errors");
7
7
  const logger_1 = require("./logger");
@@ -15,7 +15,7 @@ function createConfig(context, opts) {
15
15
  // app.use('/api', proxy({target:'http://localhost:9000'}));
16
16
  if (isContextless(context, opts)) {
17
17
  config.context = '/';
18
- config.options = _.assign(config.options, context);
18
+ config.options = Object.assign(config.options, context);
19
19
  // app.use('/api', proxy('http://localhost:9000'));
20
20
  // app.use(proxy('http://localhost:9000/api'));
21
21
  }
@@ -23,7 +23,7 @@ function createConfig(context, opts) {
23
23
  const oUrl = url.parse(context);
24
24
  const target = [oUrl.protocol, '//', oUrl.host].join('');
25
25
  config.context = oUrl.pathname || '/';
26
- config.options = _.assign(config.options, { target }, opts);
26
+ config.options = Object.assign(config.options, { target }, opts);
27
27
  if (oUrl.protocol === 'ws:' || oUrl.protocol === 'wss:') {
28
28
  config.options.ws = true;
29
29
  }
@@ -31,7 +31,7 @@ function createConfig(context, opts) {
31
31
  }
32
32
  else {
33
33
  config.context = context;
34
- config.options = _.assign(config.options, opts);
34
+ config.options = Object.assign(config.options, opts);
35
35
  }
36
36
  configureLogger(config.options);
37
37
  if (!config.options.target) {
@@ -52,7 +52,7 @@ exports.createConfig = createConfig;
52
52
  * @return {Boolean} [description]
53
53
  */
54
54
  function isStringShortHand(context) {
55
- if (_.isString(context)) {
55
+ if (typeof context === 'string') {
56
56
  return !!url.parse(context).host;
57
57
  }
58
58
  }
@@ -68,7 +68,7 @@ function isStringShortHand(context) {
68
68
  * @return {Boolean} [description]
69
69
  */
70
70
  function isContextless(context, opts) {
71
- return _.isPlainObject(context) && _.isEmpty(opts);
71
+ return isPlainObj(context) && (opts == null || Object.keys(opts).length === 0);
72
72
  }
73
73
  function configureLogger(options) {
74
74
  if (options.logLevel) {
@@ -2,7 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.match = void 0;
4
4
  const isGlob = require("is-glob");
5
- const _ = require("lodash");
6
5
  const micromatch = require("micromatch");
7
6
  const url = require("url");
8
7
  const errors_1 = require("./errors");
@@ -26,7 +25,7 @@ function match(context, uri, req) {
26
25
  throw new Error(errors_1.ERRORS.ERR_CONTEXT_MATCHER_INVALID_ARRAY);
27
26
  }
28
27
  // custom matching
29
- if (_.isFunction(context)) {
28
+ if (typeof context === 'function') {
30
29
  const pathname = getUrlPathName(uri);
31
30
  return context(pathname, req);
32
31
  }
@@ -75,7 +74,7 @@ function getUrlPathName(uri) {
75
74
  return uri && url.parse(uri).pathname;
76
75
  }
77
76
  function isStringPath(context) {
78
- return _.isString(context) && !isGlob(context);
77
+ return typeof context === 'string' && !isGlob(context);
79
78
  }
80
79
  function isGlobPath(context) {
81
80
  return isGlob(context);
package/dist/handlers.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getHandlers = exports.init = void 0;
4
- const _ = require("lodash");
4
+ const camelcase = require("camelcase");
5
5
  const logger_1 = require("./logger");
6
6
  const logger = logger_1.getInstance();
7
7
  function init(proxy, option) {
@@ -20,18 +20,18 @@ function getHandlers(options) {
20
20
  // all handlers for the http-proxy events are prefixed with 'on'.
21
21
  // loop through options and try to find these handlers
22
22
  // and add them to the handlers object for subscription in init().
23
- const eventName = _.camelCase('on ' + event);
24
- const fnHandler = _.get(options, eventName);
25
- if (_.isFunction(fnHandler)) {
23
+ const eventName = camelcase('on ' + event);
24
+ const fnHandler = options ? options[eventName] : null;
25
+ if (typeof fnHandler === 'function') {
26
26
  handlers[event] = fnHandler;
27
27
  }
28
28
  }
29
29
  // add default error handler in absence of error handler
30
- if (!_.isFunction(handlers.error)) {
30
+ if (typeof handlers.error !== 'function') {
31
31
  handlers.error = defaultErrorHandler;
32
32
  }
33
33
  // add default close handler in absence of close handler
34
- if (!_.isFunction(handlers.close)) {
34
+ if (typeof handlers.close !== 'function') {
35
35
  handlers.close = logClose;
36
36
  }
37
37
  return handlers;
@@ -49,6 +49,7 @@ function defaultErrorHandler(err, req, res) {
49
49
  case 'ECONNRESET':
50
50
  case 'ENOTFOUND':
51
51
  case 'ECONNREFUSED':
52
+ case 'ETIMEDOUT':
52
53
  res.writeHead(504);
53
54
  break;
54
55
  default:
@@ -56,7 +57,7 @@ function defaultErrorHandler(err, req, res) {
56
57
  }
57
58
  }
58
59
  }
59
- res.end('Error occured while trying to proxy to: ' + host + req.url);
60
+ res.end(`Error occured while trying to proxy: ${host}${req.url}`);
60
61
  }
61
62
  function logClose(req, socket, head) {
62
63
  // view disconnected websocket connections
@@ -3,6 +3,7 @@ export declare class HttpProxyMiddleware {
3
3
  private logger;
4
4
  private config;
5
5
  private wsInternalSubscribed;
6
+ private serverOnCloseSubscribed;
6
7
  private proxyOptions;
7
8
  private proxy;
8
9
  private pathRewriter;
@@ -11,7 +11,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.HttpProxyMiddleware = void 0;
13
13
  const httpProxy = require("http-proxy");
14
- const _ = require("lodash");
15
14
  const config_factory_1 = require("./config-factory");
16
15
  const contextMatcher = require("./context-matcher");
17
16
  const handlers = require("./handlers");
@@ -22,8 +21,10 @@ class HttpProxyMiddleware {
22
21
  constructor(context, opts) {
23
22
  this.logger = logger_1.getInstance();
24
23
  this.wsInternalSubscribed = false;
24
+ this.serverOnCloseSubscribed = false;
25
25
  // https://github.com/Microsoft/TypeScript/wiki/'this'-in-TypeScript#red-flags-for-this
26
26
  this.middleware = (req, res, next) => __awaiter(this, void 0, void 0, function* () {
27
+ var _a, _b;
27
28
  if (this.shouldProxy(this.config.context, req)) {
28
29
  try {
29
30
  const activeProxyOptions = yield this.prepareProxyRequest(req);
@@ -36,9 +37,25 @@ class HttpProxyMiddleware {
36
37
  else {
37
38
  next();
38
39
  }
40
+ /**
41
+ * Get the server object to subscribe to server events;
42
+ * 'upgrade' for websocket and 'close' for graceful shutdown
43
+ *
44
+ * NOTE:
45
+ * req.socket: node >= 13
46
+ * req.connection: node < 13 (Remove this when node 12/13 support is dropped)
47
+ */
48
+ const server = (_b = ((_a = req.socket) !== null && _a !== void 0 ? _a : req.connection)) === null || _b === void 0 ? void 0 : _b.server;
49
+ if (server && !this.serverOnCloseSubscribed) {
50
+ server.on('close', () => {
51
+ this.logger.info('[HPM] server close signal received: closing proxy server');
52
+ this.proxy.close();
53
+ });
54
+ this.serverOnCloseSubscribed = true;
55
+ }
39
56
  if (this.proxyOptions.ws === true) {
40
57
  // use initial request to access the server object to subscribe to http upgrade event
41
- this.catchUpgradeRequest(req.connection.server);
58
+ this.catchUpgradeRequest(server);
42
59
  }
43
60
  });
44
61
  this.catchUpgradeRequest = (server) => {
@@ -82,7 +99,7 @@ class HttpProxyMiddleware {
82
99
  req.url = req.originalUrl || req.url;
83
100
  // store uri before it gets rewritten for logging
84
101
  const originalPath = req.url;
85
- const newProxyOptions = _.assign({}, this.proxyOptions);
102
+ const newProxyOptions = Object.assign({}, this.proxyOptions);
86
103
  // Apply in order:
87
104
  // 1. option.router
88
105
  // 2. option.pathRewrite
package/dist/logger.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
+ /* eslint-disable prefer-rest-params */
2
3
  Object.defineProperty(exports, "__esModule", { value: true });
3
4
  exports.getArrow = exports.getInstance = void 0;
4
- const _ = require("lodash");
5
5
  const util = require("util");
6
6
  let loggerInstance;
7
7
  const defaultProvider = {
@@ -69,7 +69,7 @@ class Logger {
69
69
  }
70
70
  isValidProvider(fnProvider) {
71
71
  const result = true;
72
- if (fnProvider && !_.isFunction(fnProvider)) {
72
+ if (fnProvider && typeof fnProvider !== 'function') {
73
73
  throw new Error('[HPM] Log provider config error. Expecting a function.');
74
74
  }
75
75
  return result;
@@ -97,9 +97,8 @@ class Logger {
97
97
  }
98
98
  // make sure logged messages and its data are return interpolated
99
99
  // make it possible for additional log data, such date/time or custom prefix.
100
- _interpolate() {
101
- const fn = _.spread(util.format);
102
- const result = fn(_.slice(arguments));
100
+ _interpolate(format, ...args) {
101
+ const result = util.format(format, ...args);
103
102
  return result;
104
103
  }
105
104
  }
@@ -4,4 +4,4 @@
4
4
  * @param {Object} rewriteConfig
5
5
  * @return {Function} Function to rewrite paths; This function should accept `path` (request.url) as parameter
6
6
  */
7
- export declare function createPathRewriter(rewriteConfig: any): (...args: any[]) => any;
7
+ export declare function createPathRewriter(rewriteConfig: any): any;
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createPathRewriter = void 0;
4
- const _ = require("lodash");
4
+ const isPlainObj = require("is-plain-obj");
5
5
  const errors_1 = require("./errors");
6
6
  const logger_1 = require("./logger");
7
7
  const logger = logger_1.getInstance();
@@ -16,7 +16,7 @@ function createPathRewriter(rewriteConfig) {
16
16
  if (!isValidRewriteConfig(rewriteConfig)) {
17
17
  return;
18
18
  }
19
- if (_.isFunction(rewriteConfig)) {
19
+ if (typeof rewriteConfig === 'function') {
20
20
  const customRewriteFn = rewriteConfig;
21
21
  return customRewriteFn;
22
22
  }
@@ -26,27 +26,25 @@ function createPathRewriter(rewriteConfig) {
26
26
  }
27
27
  function rewritePath(path) {
28
28
  let result = path;
29
- _.forEach(rulesCache, (rule) => {
29
+ for (const rule of rulesCache) {
30
30
  if (rule.regex.test(path)) {
31
31
  result = result.replace(rule.regex, rule.value);
32
32
  logger.debug('[HPM] Rewriting path from "%s" to "%s"', path, result);
33
- return false;
33
+ break;
34
34
  }
35
- });
35
+ }
36
36
  return result;
37
37
  }
38
38
  }
39
39
  exports.createPathRewriter = createPathRewriter;
40
40
  function isValidRewriteConfig(rewriteConfig) {
41
- if (_.isFunction(rewriteConfig)) {
41
+ if (typeof rewriteConfig === 'function') {
42
42
  return true;
43
43
  }
44
- else if (!_.isEmpty(rewriteConfig) && _.isPlainObject(rewriteConfig)) {
45
- return true;
44
+ else if (isPlainObj(rewriteConfig)) {
45
+ return Object.keys(rewriteConfig).length !== 0;
46
46
  }
47
- else if (_.isUndefined(rewriteConfig) ||
48
- _.isNull(rewriteConfig) ||
49
- _.isEqual(rewriteConfig, {})) {
47
+ else if (rewriteConfig === undefined || rewriteConfig === null) {
50
48
  return false;
51
49
  }
52
50
  else {
@@ -55,14 +53,14 @@ function isValidRewriteConfig(rewriteConfig) {
55
53
  }
56
54
  function parsePathRewriteRules(rewriteConfig) {
57
55
  const rules = [];
58
- if (_.isPlainObject(rewriteConfig)) {
59
- _.forIn(rewriteConfig, (value, key) => {
56
+ if (isPlainObj(rewriteConfig)) {
57
+ for (const [key] of Object.entries(rewriteConfig)) {
60
58
  rules.push({
61
59
  regex: new RegExp(key),
62
60
  value: rewriteConfig[key],
63
61
  });
64
62
  logger.info('[HPM] Proxy rewrite rule created: "%s" ~> "%s"', key, rewriteConfig[key]);
65
- });
63
+ }
66
64
  }
67
65
  return rules;
68
66
  }
package/dist/router.js CHANGED
@@ -10,17 +10,17 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.getTarget = void 0;
13
- const _ = require("lodash");
13
+ const isPlainObj = require("is-plain-obj");
14
14
  const logger_1 = require("./logger");
15
15
  const logger = logger_1.getInstance();
16
16
  function getTarget(req, config) {
17
17
  return __awaiter(this, void 0, void 0, function* () {
18
18
  let newTarget;
19
19
  const router = config.router;
20
- if (_.isPlainObject(router)) {
20
+ if (isPlainObj(router)) {
21
21
  newTarget = getTargetFromProxyTable(req, router);
22
22
  }
23
- else if (_.isFunction(router)) {
23
+ else if (typeof router === 'function') {
24
24
  newTarget = yield router(req);
25
25
  }
26
26
  return newTarget;
@@ -32,13 +32,13 @@ function getTargetFromProxyTable(req, table) {
32
32
  const host = req.headers.host;
33
33
  const path = req.url;
34
34
  const hostAndPath = host + path;
35
- _.forIn(table, (value, key) => {
35
+ for (const [key] of Object.entries(table)) {
36
36
  if (containsPath(key)) {
37
37
  if (hostAndPath.indexOf(key) > -1) {
38
38
  // match 'localhost:3000/api'
39
39
  result = table[key];
40
40
  logger.debug('[HPM] Router table match: "%s"', key);
41
- return false;
41
+ break;
42
42
  }
43
43
  }
44
44
  else {
@@ -46,10 +46,10 @@ function getTargetFromProxyTable(req, table) {
46
46
  // match 'localhost:3000'
47
47
  result = table[key];
48
48
  logger.debug('[HPM] Router table match: "%s"', host);
49
- return false;
49
+ break;
50
50
  }
51
51
  }
52
- });
52
+ }
53
53
  return result;
54
54
  }
55
55
  function containsPath(v) {
package/dist/types.js CHANGED
@@ -1,2 +1,3 @@
1
1
  "use strict";
2
+ /* eslint-disable @typescript-eslint/no-empty-interface */
2
3
  Object.defineProperty(exports, "__esModule", { value: true });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "http-proxy-middleware",
3
- "version": "1.0.6",
3
+ "version": "1.1.0",
4
4
  "description": "The one-liner node.js proxy middleware for connect, express and browser-sync",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -9,10 +9,12 @@
9
9
  ],
10
10
  "scripts": {
11
11
  "clean": "rm -rf dist && rm -rf coverage",
12
- "lint": "yarn lint:prettier && yarn lint:tslint",
13
- "lint:prettier": "prettier --check \"**/*.{js,ts,md}\"",
14
- "lint:tslint": "yarn tslint -c tslint.json '{lib,test}/**/*.ts'",
15
- "lint:fix": "prettier --write \"**/*.{js,ts,md}\"",
12
+ "lint": "yarn prettier && yarn eslint",
13
+ "lint:fix": "yarn prettier:fix && yarn eslint:fix",
14
+ "eslint": "eslint '{src,test}/**/*.ts'",
15
+ "eslint:fix": "yarn eslint --fix",
16
+ "prettier": "prettier --list-different \"**/*.{js,ts,md,yml,json,html}\"",
17
+ "prettier:fix": "prettier --write \"**/*.{js,ts,md,yml,json,html}\"",
16
18
  "build": "tsc",
17
19
  "pretest": "yarn build",
18
20
  "test": "jest",
@@ -46,36 +48,40 @@
46
48
  },
47
49
  "homepage": "https://github.com/chimurai/http-proxy-middleware#readme",
48
50
  "devDependencies": {
49
- "@commitlint/cli": "^11.0.0",
50
- "@commitlint/config-conventional": "^11.0.0",
51
+ "@commitlint/cli": "^12.0.1",
52
+ "@commitlint/config-conventional": "^12.0.1",
51
53
  "@types/express": "^4.17.3",
52
54
  "@types/is-glob": "^4.0.1",
53
- "@types/jest": "^26.0.14",
54
- "@types/lodash": "^4.14.162",
55
+ "@types/jest": "^26.0.22",
55
56
  "@types/micromatch": "^4.0.1",
56
- "@types/node": "^14.11.8",
57
+ "@types/node": "^14.14.37",
57
58
  "@types/supertest": "^2.0.10",
58
- "browser-sync": "^2.26.12",
59
+ "@types/ws": "^7.4.0",
60
+ "@typescript-eslint/eslint-plugin": "^4.19.0",
61
+ "@typescript-eslint/parser": "^4.19.0",
62
+ "browser-sync": "^2.26.14",
59
63
  "connect": "^3.7.0",
64
+ "eslint": "^7.23.0",
65
+ "eslint-config-prettier": "^8.1.0",
66
+ "eslint-plugin-prettier": "^3.3.1",
60
67
  "express": "^4.17.1",
61
68
  "husky": "^4.3.0",
62
- "jest": "^26.5.3",
63
- "lint-staged": "^10.4.0",
64
- "mockttp": "^1.0.2",
65
- "open": "^7.3.0",
66
- "prettier": "^2.1.2",
67
- "supertest": "^5.0.0",
68
- "ts-jest": "^26.4.1",
69
- "tslint": "^6.1.3",
70
- "tslint-config-prettier": "^1.18.0",
71
- "typescript": "^4.0.3",
72
- "ws": "^7.3.1"
69
+ "jest": "^26.6.3",
70
+ "lint-staged": "^10.5.4",
71
+ "mockttp": "^1.2.0",
72
+ "open": "^7.4.2",
73
+ "prettier": "^2.2.1",
74
+ "supertest": "^6.1.3",
75
+ "ts-jest": "^26.5.4",
76
+ "typescript": "^4.2.3",
77
+ "ws": "^7.4.4"
73
78
  },
74
79
  "dependencies": {
75
- "@types/http-proxy": "^1.17.4",
80
+ "@types/http-proxy": "^1.17.5",
81
+ "camelcase": "^6.2.0",
76
82
  "http-proxy": "^1.18.1",
77
83
  "is-glob": "^4.0.1",
78
- "lodash": "^4.17.20",
84
+ "is-plain-obj": "^3.0.0",
79
85
  "micromatch": "^4.0.2"
80
86
  },
81
87
  "engines": {