http-proxy-middleware 3.0.3 → 3.0.5

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
@@ -38,9 +38,9 @@ import type { Filter, Options, RequestHandler } from 'http-proxy-middleware';
38
38
  const app = express();
39
39
 
40
40
  const proxyMiddleware = createProxyMiddleware<Request, Response>({
41
- target: 'http://www.example.org/api',
42
- changeOrigin: true,
43
- }),
41
+ target: 'http://www.example.org/api',
42
+ changeOrigin: true,
43
+ });
44
44
 
45
45
  app.use('/api', proxyMiddleware);
46
46
 
@@ -48,7 +48,6 @@ app.listen(3000);
48
48
 
49
49
  // proxy and keep the same base path "/api"
50
50
  // http://127.0.0.1:3000/api/foo/bar -> http://www.example.org/api/foo/bar
51
-
52
51
  ```
53
52
 
54
53
  _All_ `http-proxy` [options](https://github.com/nodejitsu/node-http-proxy#options) can be used, along with some extra `http-proxy-middleware` [options](#options).
@@ -645,4 +644,4 @@ $ yarn spellcheck
645
644
 
646
645
  The MIT License (MIT)
647
646
 
648
- Copyright (c) 2015-2024 Steven Chim
647
+ Copyright (c) 2015-2025 Steven Chim
@@ -1,8 +1,8 @@
1
1
  import type * as http from 'http';
2
2
  export type BodyParserLikeRequest = http.IncomingMessage & {
3
- body: any;
3
+ body?: any;
4
4
  };
5
5
  /**
6
6
  * Fix proxied body if bodyParser is involved.
7
7
  */
8
- export declare function fixRequestBody<TReq = http.IncomingMessage>(proxyReq: http.ClientRequest, req: TReq): void;
8
+ export declare function fixRequestBody<TReq extends BodyParserLikeRequest = BodyParserLikeRequest>(proxyReq: http.ClientRequest, req: TReq): void;
@@ -6,20 +6,45 @@ const querystring = require("querystring");
6
6
  * Fix proxied body if bodyParser is involved.
7
7
  */
8
8
  function fixRequestBody(proxyReq, req) {
9
+ // skip fixRequestBody() when req.readableLength not 0 (bodyParser failure)
10
+ if (req.readableLength !== 0) {
11
+ return;
12
+ }
9
13
  const requestBody = req.body;
10
14
  if (!requestBody) {
11
15
  return;
12
16
  }
13
17
  const contentType = proxyReq.getHeader('Content-Type');
18
+ if (!contentType) {
19
+ return;
20
+ }
14
21
  const writeBody = (bodyData) => {
15
- // deepcode ignore ContentLengthInCode: bodyParser fix
16
22
  proxyReq.setHeader('Content-Length', Buffer.byteLength(bodyData));
17
23
  proxyReq.write(bodyData);
18
24
  };
19
- if (contentType && (contentType.includes('application/json') || contentType.includes('+json'))) {
25
+ // Use if-elseif to prevent multiple writeBody/setHeader calls:
26
+ // Error: "Cannot set headers after they are sent to the client"
27
+ if (contentType.includes('application/json') || contentType.includes('+json')) {
20
28
  writeBody(JSON.stringify(requestBody));
21
29
  }
22
- if (contentType && contentType.includes('application/x-www-form-urlencoded')) {
30
+ else if (contentType.includes('application/x-www-form-urlencoded')) {
23
31
  writeBody(querystring.stringify(requestBody));
24
32
  }
33
+ else if (contentType.includes('multipart/form-data')) {
34
+ writeBody(handlerFormDataBodyData(contentType, requestBody));
35
+ }
36
+ }
37
+ /**
38
+ * format FormData data
39
+ * @param contentType
40
+ * @param data
41
+ * @returns
42
+ */
43
+ function handlerFormDataBodyData(contentType, data) {
44
+ const boundary = contentType.replace(/^.*boundary=(.*)$/, '$1');
45
+ let str = '';
46
+ for (const [key, value] of Object.entries(data)) {
47
+ str += `--${boundary}\r\nContent-Disposition: form-data; name="${key}"\r\n\r\n${value}\r\n`;
48
+ }
49
+ return str;
25
50
  }
@@ -60,10 +60,17 @@ class HttpProxyMiddleware {
60
60
  }
61
61
  };
62
62
  this.handleUpgrade = async (req, socket, head) => {
63
- if (this.shouldProxy(this.proxyOptions.pathFilter, req)) {
64
- const activeProxyOptions = await this.prepareProxyRequest(req);
65
- this.proxy.ws(req, socket, head, activeProxyOptions);
66
- (0, debug_1.Debug)('server upgrade event received. Proxying WebSocket');
63
+ try {
64
+ if (this.shouldProxy(this.proxyOptions.pathFilter, req)) {
65
+ const activeProxyOptions = await this.prepareProxyRequest(req);
66
+ this.proxy.ws(req, socket, head, activeProxyOptions);
67
+ (0, debug_1.Debug)('server upgrade event received. Proxying WebSocket');
68
+ }
69
+ }
70
+ catch (err) {
71
+ // This error does not include the URL as the fourth argument as we won't
72
+ // have the URL if `this.prepareProxyRequest` throws an error.
73
+ this.proxy.emit('error', err, req, socket);
67
74
  }
68
75
  };
69
76
  /**
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export * from './factory';
2
2
  export * from './handlers';
3
- export type { Filter, Options, RequestHandler } from './types';
3
+ export type { Plugin, Filter, Options, RequestHandler } from './types';
4
4
  /**
5
5
  * Default plugins
6
6
  */
@@ -2,18 +2,29 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.errorResponsePlugin = void 0;
4
4
  const status_code_1 = require("../../status-code");
5
+ function isResponseLike(obj) {
6
+ return obj && typeof obj.writeHead === 'function';
7
+ }
8
+ function isSocketLike(obj) {
9
+ return obj && typeof obj.write === 'function' && !('writeHead' in obj);
10
+ }
5
11
  const errorResponsePlugin = (proxyServer, options) => {
6
12
  proxyServer.on('error', (err, req, res, target) => {
7
13
  // Re-throw error. Not recoverable since req & res are empty.
8
14
  if (!req && !res) {
9
15
  throw err; // "Error: Must provide a proper URL as target"
10
16
  }
11
- if ('writeHead' in res && !res.headersSent) {
12
- const statusCode = (0, status_code_1.getStatusCode)(err.code);
13
- res.writeHead(statusCode);
17
+ if (isResponseLike(res)) {
18
+ if (!res.headersSent) {
19
+ const statusCode = (0, status_code_1.getStatusCode)(err.code);
20
+ res.writeHead(statusCode);
21
+ }
22
+ const host = req.headers && req.headers.host;
23
+ res.end(`Error occurred while trying to proxy: ${host}${req.url}`);
24
+ }
25
+ else if (isSocketLike(res)) {
26
+ res.destroy();
14
27
  }
15
- const host = req.headers && req.headers.host;
16
- res.end(`Error occurred while trying to proxy: ${host}${req.url}`);
17
28
  });
18
29
  };
19
30
  exports.errorResponsePlugin = errorResponsePlugin;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "http-proxy-middleware",
3
3
  "type": "commonjs",
4
- "version": "3.0.3",
4
+ "version": "3.0.5",
5
5
  "description": "The one-liner node.js proxy middleware for connect, express, next.js and more",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
@@ -20,7 +20,7 @@
20
20
  "build": "tsc --build",
21
21
  "test": "jest",
22
22
  "coverage": "jest --coverage",
23
- "prepare": "husky",
23
+ "prepare": "husky && patch-package",
24
24
  "prepack": "yarn clean && yarn test && yarn build",
25
25
  "spellcheck": "npx --yes cspell --show-context --show-suggestions '**/*.*'"
26
26
  },
@@ -56,37 +56,38 @@
56
56
  },
57
57
  "homepage": "https://github.com/chimurai/http-proxy-middleware#readme",
58
58
  "devDependencies": {
59
- "@commitlint/cli": "19.4.1",
60
- "@commitlint/config-conventional": "19.4.1",
61
- "@eslint/js": "9.9.1",
59
+ "@commitlint/cli": "19.8.0",
60
+ "@commitlint/config-conventional": "19.8.0",
61
+ "@eslint/js": "9.23.0",
62
62
  "@types/debug": "4.1.12",
63
63
  "@types/eslint": "9.6.1",
64
- "@types/eslint__js": "8.42.3",
65
64
  "@types/express": "4.17.21",
66
65
  "@types/is-glob": "4.0.4",
67
- "@types/jest": "29.5.12",
66
+ "@types/jest": "29.5.14",
68
67
  "@types/micromatch": "4.0.9",
69
- "@types/node": "22.5.1",
68
+ "@types/node": "22.10.2",
70
69
  "@types/supertest": "6.0.2",
71
- "@types/ws": "8.5.12",
72
- "body-parser": "1.20.2",
73
- "eslint": "9.9.1",
74
- "eslint-config-prettier": "9.1.0",
75
- "eslint-plugin-prettier": "5.2.1",
76
- "express": "4.19.2",
70
+ "@types/ws": "8.18.0",
71
+ "body-parser": "1.20.3",
72
+ "eslint": "9.23.0",
73
+ "eslint-config-prettier": "10.1.1",
74
+ "eslint-plugin-prettier": "5.2.3",
75
+ "express": "4.21.2",
77
76
  "get-port": "5.1.1",
78
- "globals": "15.9.0",
79
- "husky": "9.1.5",
77
+ "globals": "16.0.0",
78
+ "husky": "9.1.7",
80
79
  "jest": "29.7.0",
81
- "lint-staged": "15.2.9",
82
- "mockttp": "3.15.2",
80
+ "lint-staged": "15.5.0",
81
+ "mockttp": "3.17.0",
83
82
  "open": "8.4.2",
84
- "prettier": "3.3.3",
85
- "supertest": "7.0.0",
86
- "ts-jest": "29.2.5",
87
- "typescript": "5.5.4",
88
- "typescript-eslint": "8.3.0",
89
- "ws": "8.18.0"
83
+ "patch-package": "8.0.0",
84
+ "pkg-pr-new": "0.0.41",
85
+ "prettier": "3.5.3",
86
+ "supertest": "7.1.0",
87
+ "ts-jest": "29.2.6",
88
+ "typescript": "5.8.2",
89
+ "typescript-eslint": "8.27.0",
90
+ "ws": "8.18.1"
90
91
  },
91
92
  "dependencies": {
92
93
  "@types/http-proxy": "^1.17.15",