http-proxy-middleware 3.0.0-beta.1 → 3.0.1-beta.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/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![GitHub Workflow Status (with branch)](https://img.shields.io/github/actions/workflow/status/chimurai/http-proxy-middleware/ci.yml?branch=master&logo=github-actions&logoColor=white&style=flat-square)](https://github.com/chimurai/http-proxy-middleware/actions/workflows/ci.yml?query=branch%3Amaster)
4
4
  [![Coveralls](https://img.shields.io/coveralls/chimurai/http-proxy-middleware.svg?style=flat-square&logo=coveralls)](https://coveralls.io/r/chimurai/http-proxy-middleware)
5
- [![Snyk Vulnerabilities for GitHub Repo](https://img.shields.io/snyk/vulnerabilities/github/chimurai/http-proxy-middleware?logo=snyk&style=flat-square)](https://security.snyk.io/package/npm/http-proxy-middleware)
5
+ [![Known Vulnerabilities](https://snyk.io/test/github/chimurai/http-proxy-middleware/badge.svg)](https://snyk.io/test/github/chimurai/http-proxy-middleware)
6
6
  [![npm](https://img.shields.io/npm/v/http-proxy-middleware?color=%23CC3534&style=flat-square&logo=npm)](https://www.npmjs.com/package/http-proxy-middleware)
7
7
 
8
8
  Node.js proxying made simple. Configure proxy middleware with ease for [connect](https://github.com/senchalabs/connect), [express](https://github.com/expressjs/express), [next.js](https://github.com/vercel/next.js) and [many more](#compatible-servers).
@@ -39,7 +39,7 @@ app.use(
39
39
  createProxyMiddleware({
40
40
  target: 'http://www.example.org/secret',
41
41
  changeOrigin: true,
42
- })
42
+ }),
43
43
  );
44
44
 
45
45
  app.listen(3000);
@@ -61,7 +61,7 @@ app.use(
61
61
  createProxyMiddleware({
62
62
  target: 'http://www.example.org/api',
63
63
  changeOrigin: true,
64
- })
64
+ }),
65
65
  );
66
66
 
67
67
  app.listen(3000);
@@ -164,7 +164,7 @@ app.use(
164
164
  target: 'http://www.example.org/api',
165
165
  changeOrigin: true,
166
166
  pathFilter: '/api/proxy-only-this-path',
167
- })
167
+ }),
168
168
  );
169
169
  ```
170
170
 
@@ -489,7 +489,7 @@ The following options are provided by the underlying [http-proxy](https://github
489
489
  target: 'http://127.0.0.1:4003/',
490
490
  buffer: streamify(req.rawBody),
491
491
  },
492
- next
492
+ next,
493
493
  );
494
494
  };
495
495
  ```
package/dist/errors.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export declare enum ERRORS {
2
2
  ERR_CONFIG_FACTORY_TARGET_MISSING = "[HPM] Missing \"target\" option. Example: {target: \"http://www.example.org\"}",
3
- ERR_CONTEXT_MATCHER_GENERIC = "[HPM] Invalid context. Expecting something like: \"/api\" or [\"/api\", \"/ajax\"]",
4
- ERR_CONTEXT_MATCHER_INVALID_ARRAY = "[HPM] Invalid pathFilter. Expecting something like: [\"/api\", \"/ajax\"] or [\"/api/**\", \"!**.html\"]",
3
+ ERR_CONTEXT_MATCHER_GENERIC = "[HPM] Invalid pathFilter. Expecting something like: \"/api\" or [\"/api\", \"/ajax\"]",
4
+ ERR_CONTEXT_MATCHER_INVALID_ARRAY = "[HPM] Invalid pathFilter. Plain paths (e.g. \"/api\") can not be mixed with globs (e.g. \"/api/**\"). Expecting something like: [\"/api\", \"/ajax\"] or [\"/api/**\", \"!**.html\"].",
5
5
  ERR_PATH_REWRITER_CONFIG = "[HPM] Invalid pathRewrite config. Expecting object with pathRewrite config or a rewrite function"
6
6
  }
package/dist/errors.js CHANGED
@@ -4,7 +4,7 @@ exports.ERRORS = void 0;
4
4
  var ERRORS;
5
5
  (function (ERRORS) {
6
6
  ERRORS["ERR_CONFIG_FACTORY_TARGET_MISSING"] = "[HPM] Missing \"target\" option. Example: {target: \"http://www.example.org\"}";
7
- ERRORS["ERR_CONTEXT_MATCHER_GENERIC"] = "[HPM] Invalid context. Expecting something like: \"/api\" or [\"/api\", \"/ajax\"]";
8
- ERRORS["ERR_CONTEXT_MATCHER_INVALID_ARRAY"] = "[HPM] Invalid pathFilter. Expecting something like: [\"/api\", \"/ajax\"] or [\"/api/**\", \"!**.html\"]";
7
+ ERRORS["ERR_CONTEXT_MATCHER_GENERIC"] = "[HPM] Invalid pathFilter. Expecting something like: \"/api\" or [\"/api\", \"/ajax\"]";
8
+ ERRORS["ERR_CONTEXT_MATCHER_INVALID_ARRAY"] = "[HPM] Invalid pathFilter. Plain paths (e.g. \"/api\") can not be mixed with globs (e.g. \"/api/**\"). Expecting something like: [\"/api\", \"/ajax\"] or [\"/api/**\", \"!**.html\"].";
9
9
  ERRORS["ERR_PATH_REWRITER_CONFIG"] = "[HPM] Invalid pathRewrite config. Expecting object with pathRewrite config or a rewrite function";
10
- })(ERRORS = exports.ERRORS || (exports.ERRORS = {}));
10
+ })(ERRORS || (exports.ERRORS = ERRORS = {}));
@@ -3,13 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getPlugins = void 0;
4
4
  const default_1 = require("./plugins/default");
5
5
  function getPlugins(options) {
6
- var _a, _b;
7
6
  // don't load default errorResponsePlugin if user has specified their own
8
- const maybeErrorResponsePlugin = !!((_a = options.on) === null || _a === void 0 ? void 0 : _a.error) ? [] : [default_1.errorResponsePlugin];
7
+ const maybeErrorResponsePlugin = !!options.on?.error ? [] : [default_1.errorResponsePlugin];
9
8
  const defaultPlugins = !!options.ejectPlugins
10
9
  ? [] // no default plugins when ejecting
11
10
  : [default_1.debugProxyErrorsPlugin, default_1.proxyEventsPlugin, default_1.loggerPlugin, ...maybeErrorResponsePlugin];
12
- const userPlugins = (_b = options.plugins) !== null && _b !== void 0 ? _b : [];
11
+ const userPlugins = options.plugins ?? [];
13
12
  return [...defaultPlugins, ...userPlugins];
14
13
  }
15
14
  exports.getPlugins = getPlugins;
@@ -1,6 +1,6 @@
1
1
  /// <reference types="node" />
2
2
  import type * as http from 'http';
3
- export declare type BodyParserLikeRequest = http.IncomingMessage & {
3
+ export type BodyParserLikeRequest = http.IncomingMessage & {
4
4
  body: any;
5
5
  };
6
6
  /**
@@ -1,7 +1,7 @@
1
1
  /// <reference types="node" />
2
2
  /// <reference types="node" />
3
3
  import type * as http from 'http';
4
- declare type Interceptor<TReq = http.IncomingMessage, TRes = http.ServerResponse> = (buffer: Buffer, proxyRes: TReq, req: TReq, res: TRes) => Promise<Buffer | string>;
4
+ type Interceptor<TReq = http.IncomingMessage, TRes = http.ServerResponse> = (buffer: Buffer, proxyRes: TReq, req: TReq, res: TRes) => Promise<Buffer | string>;
5
5
  /**
6
6
  * Intercept responses from upstream.
7
7
  * Automatically decompress (deflate, gzip, brotli).
@@ -14,8 +14,7 @@ class HttpProxyMiddleware {
14
14
  this.wsInternalSubscribed = false;
15
15
  this.serverOnCloseSubscribed = false;
16
16
  // https://github.com/Microsoft/TypeScript/wiki/'this'-in-TypeScript#red-flags-for-this
17
- this.middleware = async (req, res, next) => {
18
- var _a, _b;
17
+ this.middleware = (async (req, res, next) => {
19
18
  if (this.shouldProxy(this.proxyOptions.pathFilter, req)) {
20
19
  try {
21
20
  const activeProxyOptions = await this.prepareProxyRequest(req);
@@ -37,7 +36,7 @@ class HttpProxyMiddleware {
37
36
  * req.socket: node >= 13
38
37
  * req.connection: node < 13 (Remove this when node 12/13 support is dropped)
39
38
  */
40
- const server = (_b = (((_a = req.socket) !== null && _a !== void 0 ? _a : req.connection))) === null || _b === void 0 ? void 0 : _b.server;
39
+ const server = (req.socket ?? req.connection)?.server;
41
40
  if (server && !this.serverOnCloseSubscribed) {
42
41
  server.on('close', () => {
43
42
  (0, debug_1.Debug)('server close signal received: closing proxy server');
@@ -49,7 +48,7 @@ class HttpProxyMiddleware {
49
48
  // use initial request to access the server object to subscribe to http upgrade event
50
49
  this.catchUpgradeRequest(server);
51
50
  }
52
- };
51
+ });
53
52
  this.catchUpgradeRequest = (server) => {
54
53
  if (!this.wsInternalSubscribed) {
55
54
  (0, debug_1.Debug)('subscribing to server upgrade event');
@@ -18,12 +18,15 @@ const proxyEventMap = {
18
18
  * Convert {@link LegacyOptions legacy Options} to new {@link Options}
19
19
  */
20
20
  function legacyOptionsAdapter(legacyContext, legacyOptions) {
21
- let options;
21
+ let options = {};
22
22
  let logger;
23
23
  // https://github.com/chimurai/http-proxy-middleware/pull/716
24
24
  if (typeof legacyContext === 'string' && !!url.parse(legacyContext).host) {
25
25
  throw new Error(`Shorthand syntax is removed from legacyCreateProxyMiddleware().
26
- Please use "legacyCreateProxyMiddleware({ target: 'http://www.example.org' })" instead.`);
26
+ Please use "legacyCreateProxyMiddleware({ target: 'http://www.example.org' })" instead.
27
+
28
+ More details: https://github.com/chimurai/http-proxy-middleware/blob/master/MIGRATION.md#removed-shorthand-usage
29
+ `);
27
30
  }
28
31
  // detect old "context" argument and convert to "options.pathFilter"
29
32
  // https://github.com/chimurai/http-proxy-middleware/pull/722/files#diff-a2a171449d862fe29692ce031981047d7ab755ae7f84c707aef80701b3ea0c80L4
@@ -37,13 +40,16 @@ function legacyOptionsAdapter(legacyContext, legacyOptions) {
37
40
  pathFilter: '${legacyContext}',
38
41
  }
39
42
 
40
- More details: https://github.com/chimurai/http-proxy-middleware/blob/master/MIGRATION.md
43
+ More details: https://github.com/chimurai/http-proxy-middleware/blob/master/MIGRATION.md#removed-context-argument
41
44
  `);
42
45
  }
43
46
  else if (legacyContext && !legacyOptions) {
44
47
  options = { ...legacyContext };
45
48
  logger = getLegacyLogger(options);
46
49
  }
50
+ else {
51
+ logger = getLegacyLogger({});
52
+ }
47
53
  // map old event names to new event names
48
54
  // https://github.com/chimurai/http-proxy-middleware/pull/745/files#diff-c54113cf61ec99691748a3890bfbeb00e10efb3f0a76f03a0fd9ec49072e410aL48-L53
49
55
  Object.entries(proxyEventMap).forEach(([legacyEventName, proxyEventName]) => {
@@ -59,7 +65,7 @@ function legacyOptionsAdapter(legacyContext, legacyOptions) {
59
65
  },
60
66
  }
61
67
 
62
- More details: https://github.com/chimurai/http-proxy-middleware/blob/master/MIGRATION.md
68
+ More details: https://github.com/chimurai/http-proxy-middleware/blob/master/MIGRATION.md#refactored-proxy-events
63
69
  `);
64
70
  }
65
71
  });
@@ -77,7 +83,7 @@ function legacyOptionsAdapter(legacyContext, legacyOptions) {
77
83
  logger: console,
78
84
  }
79
85
 
80
- More details: https://github.com/chimurai/http-proxy-middleware/blob/master/MIGRATION.md
86
+ More details: https://github.com/chimurai/http-proxy-middleware/blob/master/MIGRATION.md#removed-logprovider-and-loglevel-options
81
87
  `);
82
88
  }
83
89
  return options;
@@ -1,4 +1,4 @@
1
1
  /// <reference types="node" />
2
2
  import type { Filter } from './types';
3
3
  import type * as http from 'http';
4
- export declare function matchPathFilter<TReq = http.IncomingMessage>(pathFilter: Filter<TReq>, uri: string, req: http.IncomingMessage): boolean;
4
+ export declare function matchPathFilter<TReq = http.IncomingMessage>(pathFilter: Filter<TReq> | undefined, uri: string | undefined, req: http.IncomingMessage): boolean;
@@ -39,7 +39,7 @@ exports.matchPathFilter = matchPathFilter;
39
39
  */
40
40
  function matchSingleStringPath(pathFilter, uri) {
41
41
  const pathname = getUrlPathName(uri);
42
- return pathname.indexOf(pathFilter) === 0;
42
+ return pathname?.indexOf(pathFilter) === 0;
43
43
  }
44
44
  function matchSingleGlobPath(pattern, uri) {
45
45
  const pathname = getUrlPathName(uri);
@@ -8,7 +8,7 @@ const errorResponsePlugin = (proxyServer, options) => {
8
8
  if (!req && !res) {
9
9
  throw err; // "Error: Must provide a proper URL as target"
10
10
  }
11
- if (res.writeHead && !res.headersSent) {
11
+ if ('writeHead' in res && !res.headersSent) {
12
12
  const statusCode = (0, status_code_1.getStatusCode)(err.code);
13
13
  res.writeHead(statusCode);
14
14
  }
@@ -1,14 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.loggerPlugin = void 0;
4
+ const url_1 = require("url");
4
5
  const logger_1 = require("../../logger");
5
6
  const loggerPlugin = (proxyServer, options) => {
6
7
  const logger = (0, logger_1.getLogger)(options);
7
8
  proxyServer.on('error', (err, req, res, target) => {
8
- var _a;
9
- const hostname = (_a = req === null || req === void 0 ? void 0 : req.headers) === null || _a === void 0 ? void 0 : _a.host;
10
- const requestHref = `${hostname}${req === null || req === void 0 ? void 0 : req.url}`;
11
- const targetHref = `${target === null || target === void 0 ? void 0 : target.href}`; // target is undefined when websocket errors
9
+ const hostname = req?.headers?.host;
10
+ const requestHref = `${hostname}${req?.url}`;
11
+ const targetHref = `${target?.href}`; // target is undefined when websocket errors
12
12
  const errorMessage = '[HPM] Error occurred while proxying request %s to %s [%s] (%s)';
13
13
  const errReference = 'https://nodejs.org/api/errors.html#errors_common_system_errors'; // link to Node Common Systems Errors page
14
14
  logger.error(errorMessage, requestHref, targetHref, err.code || err, errReference);
@@ -21,11 +21,14 @@ const loggerPlugin = (proxyServer, options) => {
21
21
  * ```
22
22
  */
23
23
  proxyServer.on('proxyRes', (proxyRes, req, res) => {
24
- var _a;
25
24
  // BrowserSync uses req.originalUrl
26
25
  // Next.js doesn't have req.baseUrl
27
- const originalUrl = (_a = req.originalUrl) !== null && _a !== void 0 ? _a : `${req.baseUrl || ''}${req.url}`;
28
- const exchange = `[HPM] ${req.method} ${originalUrl} -> ${proxyRes.req.protocol}//${proxyRes.req.host}${proxyRes.req.path} [${proxyRes.statusCode}]`;
26
+ const originalUrl = req.originalUrl ?? `${req.baseUrl || ''}${req.url}`;
27
+ // construct targetUrl
28
+ const target = new url_1.URL(options.target);
29
+ target.pathname = proxyRes.req.path;
30
+ const targetUrl = target.toString();
31
+ const exchange = `[HPM] ${req.method} ${originalUrl} -> ${targetUrl} [${proxyRes.statusCode}]`;
29
32
  logger.info(exchange);
30
33
  });
31
34
  /**
package/dist/types.d.ts CHANGED
@@ -5,15 +5,16 @@
5
5
  /// <reference types="node" />
6
6
  /// <reference types="node" />
7
7
  /// <reference types="node" />
8
+ /// <reference types="node" />
8
9
  import type * as http from 'http';
9
10
  import type * as httpProxy from 'http-proxy';
10
11
  import type * as net from 'net';
11
- export declare type NextFunction<T = (err?: any) => void> = T;
12
+ export type NextFunction<T = (err?: any) => void> = T;
12
13
  export interface RequestHandler<TReq = http.IncomingMessage, TRes = http.ServerResponse, TNext = NextFunction> {
13
- (req: TReq, res: TRes, next?: TNext): void | Promise<void>;
14
- upgrade?: (req: http.IncomingMessage, socket: net.Socket, head: any) => void;
14
+ (req: TReq, res: TRes, next?: TNext): Promise<void>;
15
+ upgrade: (req: http.IncomingMessage, socket: net.Socket, head: Buffer) => void;
15
16
  }
16
- export declare type Filter<TReq = http.IncomingMessage> = string | string[] | ((pathname: string, req: TReq) => boolean);
17
+ export type Filter<TReq = http.IncomingMessage> = string | string[] | ((pathname: string, req: TReq) => boolean);
17
18
  export interface Plugin<TReq = http.IncomingMessage, TRes = http.ServerResponse> {
18
19
  (proxyServer: httpProxy<TReq, TRes>, options: Options<TReq, TRes>): void;
19
20
  }
@@ -28,7 +29,7 @@ export interface OnProxyEvent<TReq = http.IncomingMessage, TRes = http.ServerRes
28
29
  end?: httpProxy.EndCallback<TReq, TRes>;
29
30
  econnreset?: httpProxy.EconnresetCallback<Error, TReq, TRes>;
30
31
  }
31
- export declare type Logger = Pick<Console, 'info' | 'warn' | 'error'>;
32
+ export type Logger = Pick<Console, 'info' | 'warn' | 'error'>;
32
33
  export interface Options<TReq = http.IncomingMessage, TRes = http.ServerResponse> extends httpProxy.ServerOptions {
33
34
  /**
34
35
  * Narrow down requests to proxy or not.
@@ -52,7 +53,7 @@ export interface Options<TReq = http.IncomingMessage, TRes = http.ServerResponse
52
53
  */
53
54
  pathRewrite?: {
54
55
  [regexp: string]: string;
55
- } | ((path: string, req: TReq) => string) | ((path: string, req: TReq) => Promise<string>);
56
+ } | ((path: string, req: TReq) => string | undefined) | ((path: string, req: TReq) => Promise<string>);
56
57
  /**
57
58
  * Access the internal http-proxy server instance to customize behavior
58
59
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "http-proxy-middleware",
3
- "version": "3.0.0-beta.1",
3
+ "version": "3.0.1-beta.0",
4
4
  "description": "The one-liner node.js proxy middleware for connect, express, next.js and more",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -18,10 +18,13 @@
18
18
  "build": "tsc --build",
19
19
  "test": "jest",
20
20
  "coverage": "jest --coverage",
21
- "prepare": "husky install",
21
+ "prepare": "husky",
22
22
  "prepack": "yarn clean && yarn test && yarn build",
23
23
  "spellcheck": "npx --yes cspell --show-context --show-suggestions '**/*.*'"
24
24
  },
25
+ "publishConfig": {
26
+ "provenance": true
27
+ },
25
28
  "repository": {
26
29
  "type": "git",
27
30
  "url": "https://github.com/chimurai/http-proxy-middleware.git"
@@ -51,36 +54,36 @@
51
54
  },
52
55
  "homepage": "https://github.com/chimurai/http-proxy-middleware#readme",
53
56
  "devDependencies": {
54
- "@commitlint/cli": "17.4.4",
55
- "@commitlint/config-conventional": "17.4.4",
56
- "@types/debug": "4.1.7",
57
- "@types/express": "4.17.17",
58
- "@types/is-glob": "4.0.2",
59
- "@types/jest": "29.4.0",
60
- "@types/micromatch": "4.0.2",
61
- "@types/node": "18.14.5",
62
- "@types/supertest": "2.0.12",
63
- "@types/ws": "8.5.4",
64
- "@typescript-eslint/eslint-plugin": "5.54.0",
65
- "@typescript-eslint/parser": "5.54.0",
57
+ "@commitlint/cli": "19.2.1",
58
+ "@commitlint/config-conventional": "19.1.0",
59
+ "@types/debug": "4.1.12",
60
+ "@types/express": "4.17.21",
61
+ "@types/is-glob": "4.0.4",
62
+ "@types/jest": "29.5.12",
63
+ "@types/micromatch": "4.0.6",
64
+ "@types/node": "20.12.5",
65
+ "@types/supertest": "6.0.2",
66
+ "@types/ws": "8.5.10",
67
+ "@typescript-eslint/eslint-plugin": "7.6.0",
68
+ "@typescript-eslint/parser": "7.6.0",
66
69
  "body-parser": "1.20.2",
67
- "browser-sync": "2.28.1",
70
+ "browser-sync": "3.0.2",
68
71
  "connect": "3.7.0",
69
- "eslint": "8.35.0",
70
- "eslint-config-prettier": "8.6.0",
71
- "eslint-plugin-prettier": "4.2.1",
72
- "express": "4.18.2",
72
+ "eslint": "8.57.0",
73
+ "eslint-config-prettier": "9.1.0",
74
+ "eslint-plugin-prettier": "5.1.3",
75
+ "express": "4.19.2",
73
76
  "get-port": "5.1.1",
74
- "husky": "8.0.3",
75
- "jest": "29.4.3",
76
- "lint-staged": "13.1.2",
77
- "mockttp": "3.7.0",
77
+ "husky": "9.0.11",
78
+ "jest": "29.7.0",
79
+ "lint-staged": "15.2.2",
80
+ "mockttp": "3.10.2",
78
81
  "open": "8.4.2",
79
- "prettier": "2.8.4",
80
- "supertest": "6.3.3",
81
- "ts-jest": "29.0.5",
82
- "typescript": "4.9.5",
83
- "ws": "8.12.1"
82
+ "prettier": "3.2.5",
83
+ "supertest": "6.3.4",
84
+ "ts-jest": "29.1.2",
85
+ "typescript": "5.4.4",
86
+ "ws": "8.16.0"
84
87
  },
85
88
  "dependencies": {
86
89
  "@types/http-proxy": "^1.17.10",
@@ -91,7 +94,7 @@
91
94
  "micromatch": "^4.0.5"
92
95
  },
93
96
  "engines": {
94
- "node": ">=12.0.0"
97
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
95
98
  },
96
99
  "commitlint": {
97
100
  "extends": [