http-proxy-middleware 3.0.0-beta.0 → 3.0.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 +39 -26
- package/dist/configuration.d.ts +1 -1
- package/dist/errors.js +1 -1
- package/dist/get-plugins.d.ts +1 -1
- package/dist/get-plugins.js +2 -3
- package/dist/handlers/fix-request-body.d.ts +4 -2
- package/dist/handlers/response-interceptor.d.ts +3 -2
- package/dist/http-proxy-middleware.d.ts +2 -2
- package/dist/http-proxy-middleware.js +3 -4
- package/dist/index.d.ts +4 -2
- package/dist/legacy/create-proxy-middleware.d.ts +5 -3
- package/dist/legacy/options-adapter.d.ts +1 -1
- package/dist/legacy/options-adapter.js +11 -5
- package/dist/legacy/types.d.ts +3 -1
- package/dist/path-filter.d.ts +4 -2
- package/dist/path-filter.js +1 -1
- package/dist/plugins/default/error-response-plugin.js +1 -1
- package/dist/plugins/default/logger-plugin.js +5 -6
- package/dist/types.d.ts +61 -25
- package/package.json +36 -50
package/README.md
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# http-proxy-middleware
|
|
2
2
|
|
|
3
|
-
[](https://coveralls.io/r/chimurai/http-proxy-middleware)
|
|
5
|
-
[](https://www.npmjs.com/package/http-proxy-middleware)
|
|
3
|
+
[](https://github.com/chimurai/http-proxy-middleware/actions/workflows/ci.yml?query=branch%3Amaster)
|
|
4
|
+
[](https://coveralls.io/r/chimurai/http-proxy-middleware)
|
|
5
|
+
[](https://snyk.io/test/github/chimurai/http-proxy-middleware)
|
|
6
|
+
[](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).
|
|
9
9
|
|
|
10
|
-
Powered by the popular Nodejitsu [`http-proxy`](https://github.com/
|
|
10
|
+
Powered by the popular Nodejitsu [`http-proxy`](https://github.com/http-party/node-http-proxy). [](https://github.com/http-party/node-http-proxy)
|
|
11
11
|
|
|
12
12
|
## ⚠️ Note <!-- omit in toc -->
|
|
13
13
|
|
|
@@ -39,13 +39,13 @@ 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);
|
|
46
46
|
|
|
47
47
|
// proxy and change the base path from "/api" to "/secret"
|
|
48
|
-
// http://
|
|
48
|
+
// http://127.0.0.1:3000/api/foo/bar -> http://www.example.org/secret/foo/bar
|
|
49
49
|
```
|
|
50
50
|
|
|
51
51
|
```typescript
|
|
@@ -61,13 +61,13 @@ 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);
|
|
68
68
|
|
|
69
69
|
// proxy and keep the same base path "/api"
|
|
70
|
-
// http://
|
|
70
|
+
// http://127.0.0.1:3000/api/foo/bar -> http://www.example.org/api/foo/bar
|
|
71
71
|
```
|
|
72
72
|
|
|
73
73
|
_All_ `http-proxy` [options](https://github.com/nodejitsu/node-http-proxy#options) can be used, along with some extra `http-proxy-middleware` [options](#options).
|
|
@@ -81,7 +81,7 @@ _All_ `http-proxy` [options](https://github.com/nodejitsu/node-http-proxy#option
|
|
|
81
81
|
- [Express Server Example](#express-server-example)
|
|
82
82
|
- [app.use(path, proxy)](#appusepath-proxy)
|
|
83
83
|
- [Options](#options)
|
|
84
|
-
- [`pathFilter` (string, []string, glob, []glob, function)](#pathfilter-string-string-glob-glob-function)
|
|
84
|
+
- [`pathFilter` (string, \[\]string, glob, \[\]glob, function)](#pathfilter-string-string-glob-glob-function)
|
|
85
85
|
- [`pathRewrite` (object/function)](#pathrewrite-objectfunction)
|
|
86
86
|
- [`router` (object/function)](#router-objectfunction)
|
|
87
87
|
- [`plugins` (Array)](#plugins-array)
|
|
@@ -93,6 +93,7 @@ _All_ `http-proxy` [options](https://github.com/nodejitsu/node-http-proxy#option
|
|
|
93
93
|
- [External WebSocket upgrade](#external-websocket-upgrade)
|
|
94
94
|
- [Intercept and manipulate requests](#intercept-and-manipulate-requests)
|
|
95
95
|
- [Intercept and manipulate responses](#intercept-and-manipulate-responses)
|
|
96
|
+
- [Node.js 17+: ECONNREFUSED issue with IPv6 and localhost (#705)](#nodejs-17-econnrefused-issue-with-ipv6-and-localhost-705)
|
|
96
97
|
- [Debugging](#debugging)
|
|
97
98
|
- [Working examples](#working-examples)
|
|
98
99
|
- [Recipes](#recipes)
|
|
@@ -140,15 +141,12 @@ const { createProxyMiddleware } = require('http-proxy-middleware');
|
|
|
140
141
|
|
|
141
142
|
const app = express();
|
|
142
143
|
|
|
143
|
-
//
|
|
144
|
-
/** @type {import('http-proxy-middleware/dist/types').
|
|
145
|
-
const
|
|
144
|
+
// create the proxy
|
|
145
|
+
/** @type {import('http-proxy-middleware/dist/types').RequestHandler<express.Request, express.Response>} */
|
|
146
|
+
const exampleProxy = createProxyMiddleware({
|
|
146
147
|
target: 'http://www.example.org/api', // target host with the same base path
|
|
147
148
|
changeOrigin: true, // needed for virtual hosted sites
|
|
148
|
-
};
|
|
149
|
-
|
|
150
|
-
// create the proxy
|
|
151
|
-
const exampleProxy = createProxyMiddleware(options);
|
|
149
|
+
});
|
|
152
150
|
|
|
153
151
|
// mount `exampleProxy` in web server
|
|
154
152
|
app.use('/api', exampleProxy);
|
|
@@ -166,7 +164,7 @@ app.use(
|
|
|
166
164
|
target: 'http://www.example.org/api',
|
|
167
165
|
changeOrigin: true,
|
|
168
166
|
pathFilter: '/api/proxy-only-this-path',
|
|
169
|
-
})
|
|
167
|
+
}),
|
|
170
168
|
);
|
|
171
169
|
```
|
|
172
170
|
|
|
@@ -257,22 +255,22 @@ Re-target `option.target` for specific requests.
|
|
|
257
255
|
// Use `host` and/or `path` to match requests. First match will be used.
|
|
258
256
|
// The order of the configuration matters.
|
|
259
257
|
router: {
|
|
260
|
-
'integration.localhost:3000' : 'http://
|
|
261
|
-
'staging.localhost:3000' : 'http://
|
|
262
|
-
'localhost:3000/api' : 'http://
|
|
263
|
-
'/rest' : 'http://
|
|
258
|
+
'integration.localhost:3000' : 'http://127.0.0.1:8001', // host only
|
|
259
|
+
'staging.localhost:3000' : 'http://127.0.0.1:8002', // host only
|
|
260
|
+
'localhost:3000/api' : 'http://127.0.0.1:8003', // host + path
|
|
261
|
+
'/rest' : 'http://127.0.0.1:8004' // path only
|
|
264
262
|
}
|
|
265
263
|
|
|
266
264
|
// Custom router function (string target)
|
|
267
265
|
router: function(req) {
|
|
268
|
-
return 'http://
|
|
266
|
+
return 'http://127.0.0.1:8004';
|
|
269
267
|
}
|
|
270
268
|
|
|
271
269
|
// Custom router function (target object)
|
|
272
270
|
router: function(req) {
|
|
273
271
|
return {
|
|
274
272
|
protocol: 'https:', // The : is required
|
|
275
|
-
host: '
|
|
273
|
+
host: '127.0.0.1',
|
|
276
274
|
port: 8004
|
|
277
275
|
};
|
|
278
276
|
}
|
|
@@ -488,10 +486,10 @@ The following options are provided by the underlying [http-proxy](https://github
|
|
|
488
486
|
req,
|
|
489
487
|
res,
|
|
490
488
|
{
|
|
491
|
-
target: 'http://
|
|
489
|
+
target: 'http://127.0.0.1:4003/',
|
|
492
490
|
buffer: streamify(req.rawBody),
|
|
493
491
|
},
|
|
494
|
-
next
|
|
492
|
+
next,
|
|
495
493
|
);
|
|
496
494
|
};
|
|
497
495
|
```
|
|
@@ -573,6 +571,21 @@ const proxy = createProxyMiddleware({
|
|
|
573
571
|
|
|
574
572
|
Check out [interception recipes](https://github.com/chimurai/http-proxy-middleware/blob/master/recipes/response-interceptor.md#readme) for more examples.
|
|
575
573
|
|
|
574
|
+
## Node.js 17+: ECONNREFUSED issue with IPv6 and localhost ([#705](https://github.com/chimurai/http-proxy-middleware/issues/705))
|
|
575
|
+
|
|
576
|
+
Node.js 17+ no longer prefers IPv4 over IPv6 for DNS lookups.
|
|
577
|
+
E.g. It's **not** guaranteed that `localhost` will be resolved to `127.0.0.1` – it might just as well be `::1` (or some other IP address).
|
|
578
|
+
|
|
579
|
+
If your target server only accepts IPv4 connections, trying to proxy to `localhost` will fail if resolved to `::1` (IPv6).
|
|
580
|
+
|
|
581
|
+
Ways to solve it:
|
|
582
|
+
|
|
583
|
+
- Change `target: "http://localhost"` to `target: "http://127.0.0.1"` (IPv4).
|
|
584
|
+
- Change the target server to (also) accept IPv6 connections.
|
|
585
|
+
- Add this flag when running `node`: `node index.js --dns-result-order=ipv4first`. (Not recommended.)
|
|
586
|
+
|
|
587
|
+
> Note: There’s a thing called [Happy Eyeballs](https://en.wikipedia.org/wiki/Happy_Eyeballs) which means connecting to both IPv4 and IPv6 in parallel, which Node.js doesn’t have, but explains why for example `curl` can connect.
|
|
588
|
+
|
|
576
589
|
## Debugging
|
|
577
590
|
|
|
578
591
|
Configure the `DEBUG` environment variable enable debug logging.
|
package/dist/configuration.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { Options } from './types';
|
|
2
|
-
export declare function verifyConfig(options: Options): void;
|
|
2
|
+
export declare function verifyConfig<TReq, TRes>(options: Options<TReq, TRes>): void;
|
package/dist/errors.js
CHANGED
|
@@ -7,4 +7,4 @@ var ERRORS;
|
|
|
7
7
|
ERRORS["ERR_CONTEXT_MATCHER_GENERIC"] = "[HPM] Invalid context. Expecting something like: \"/api\" or [\"/api\", \"/ajax\"]";
|
|
8
8
|
ERRORS["ERR_CONTEXT_MATCHER_INVALID_ARRAY"] = "[HPM] Invalid pathFilter. 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
|
|
10
|
+
})(ERRORS || (exports.ERRORS = ERRORS = {}));
|
package/dist/get-plugins.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { Options, Plugin } from './types';
|
|
2
|
-
export declare function getPlugins(options: Options): Plugin[];
|
|
2
|
+
export declare function getPlugins<TReq, TRes>(options: Options<TReq, TRes>): Plugin<TReq, TRes>[];
|
package/dist/get-plugins.js
CHANGED
|
@@ -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 = !!
|
|
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 =
|
|
11
|
+
const userPlugins = options.plugins ?? [];
|
|
13
12
|
return [...defaultPlugins, ...userPlugins];
|
|
14
13
|
}
|
|
15
14
|
exports.getPlugins = getPlugins;
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import type * as http from 'http';
|
|
3
|
-
|
|
3
|
+
export type BodyParserLikeRequest = http.IncomingMessage & {
|
|
4
|
+
body: any;
|
|
5
|
+
};
|
|
4
6
|
/**
|
|
5
7
|
* Fix proxied body if bodyParser is involved.
|
|
6
8
|
*/
|
|
7
|
-
export declare function fixRequestBody(proxyReq: http.ClientRequest, req:
|
|
9
|
+
export declare function fixRequestBody<TReq = http.IncomingMessage>(proxyReq: http.ClientRequest, req: TReq): void;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
+
/// <reference types="node" />
|
|
2
3
|
import type * as http from 'http';
|
|
3
|
-
|
|
4
|
+
type Interceptor<TReq = http.IncomingMessage, TRes = http.ServerResponse> = (buffer: Buffer, proxyRes: TReq, req: TReq, res: TRes) => Promise<Buffer | string>;
|
|
4
5
|
/**
|
|
5
6
|
* Intercept responses from upstream.
|
|
6
7
|
* Automatically decompress (deflate, gzip, brotli).
|
|
@@ -8,5 +9,5 @@ declare type Interceptor = (buffer: Buffer, proxyRes: http.IncomingMessage, req:
|
|
|
8
9
|
*
|
|
9
10
|
* NOTE: must set options.selfHandleResponse=true (prevent automatic call of res.end())
|
|
10
11
|
*/
|
|
11
|
-
export declare function responseInterceptor(interceptor: Interceptor): (proxyRes:
|
|
12
|
+
export declare function responseInterceptor<TReq extends http.IncomingMessage = http.IncomingMessage, TRes extends http.ServerResponse = http.ServerResponse>(interceptor: Interceptor<TReq, TRes>): (proxyRes: TReq, req: TReq, res: TRes) => Promise<void>;
|
|
12
13
|
export {};
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import type { RequestHandler, Options } from './types';
|
|
2
|
-
export declare class HttpProxyMiddleware {
|
|
2
|
+
export declare class HttpProxyMiddleware<TReq, TRes> {
|
|
3
3
|
private wsInternalSubscribed;
|
|
4
4
|
private serverOnCloseSubscribed;
|
|
5
5
|
private proxyOptions;
|
|
6
6
|
private proxy;
|
|
7
7
|
private pathRewriter;
|
|
8
|
-
constructor(options: Options);
|
|
8
|
+
constructor(options: Options<TReq, TRes>);
|
|
9
9
|
middleware: RequestHandler;
|
|
10
10
|
private registerPlugins;
|
|
11
11
|
private catchUpgradeRequest;
|
|
@@ -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 = (
|
|
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');
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import type { Options, RequestHandler, NextFunction } from './types';
|
|
3
|
+
import type * as http from 'http';
|
|
4
|
+
export declare function createProxyMiddleware<TReq = http.IncomingMessage, TRes = http.ServerResponse, TNext = NextFunction>(options: Options<TReq, TRes>): RequestHandler<TReq, TRes, TNext>;
|
|
3
5
|
export * from './handlers';
|
|
4
6
|
export type { Filter, Options, RequestHandler } from './types';
|
|
5
7
|
/**
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
1
2
|
import { Filter, RequestHandler } from '../types';
|
|
2
3
|
import { LegacyOptions } from './types';
|
|
4
|
+
import type * as http from 'http';
|
|
3
5
|
/**
|
|
4
6
|
* @deprecated
|
|
5
7
|
* This function is deprecated and will be removed in a future version.
|
|
6
8
|
*
|
|
7
9
|
* Use {@link createProxyMiddleware} instead.
|
|
8
10
|
*/
|
|
9
|
-
export declare function legacyCreateProxyMiddleware(shortHand: string): RequestHandler
|
|
10
|
-
export declare function legacyCreateProxyMiddleware(legacyOptions: LegacyOptions): RequestHandler
|
|
11
|
-
export declare function legacyCreateProxyMiddleware(legacyContext: Filter
|
|
11
|
+
export declare function legacyCreateProxyMiddleware<TReq = http.IncomingMessage, TRes = http.ServerResponse>(shortHand: string): RequestHandler<TReq, TRes>;
|
|
12
|
+
export declare function legacyCreateProxyMiddleware<TReq = http.IncomingMessage, TRes = http.ServerResponse>(legacyOptions: LegacyOptions<TReq, TRes>): RequestHandler<TReq, TRes>;
|
|
13
|
+
export declare function legacyCreateProxyMiddleware<TReq = http.IncomingMessage, TRes = http.ServerResponse>(legacyContext: Filter<TReq>, legacyOptions: LegacyOptions<TReq, TRes>): RequestHandler<TReq, TRes>;
|
|
@@ -3,4 +3,4 @@ import { LegacyOptions } from './types';
|
|
|
3
3
|
/**
|
|
4
4
|
* Convert {@link LegacyOptions legacy Options} to new {@link Options}
|
|
5
5
|
*/
|
|
6
|
-
export declare function legacyOptionsAdapter(legacyContext: Filter | LegacyOptions, legacyOptions: LegacyOptions): Options
|
|
6
|
+
export declare function legacyOptionsAdapter<TReq, TRes>(legacyContext: Filter<TReq> | LegacyOptions<TReq, TRes>, legacyOptions: LegacyOptions<TReq, TRes>): Options<TReq, TRes>;
|
|
@@ -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;
|
package/dist/legacy/types.d.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import type * as http from 'http';
|
|
1
3
|
import { Options } from '..';
|
|
2
4
|
/**
|
|
3
5
|
* @deprecated
|
|
4
6
|
*
|
|
5
7
|
* Will be removed in a future version.
|
|
6
8
|
*/
|
|
7
|
-
export interface LegacyOptions extends Options {
|
|
9
|
+
export interface LegacyOptions<TReq = http.IncomingMessage, TRes = http.ServerResponse> extends Options<TReq, TRes> {
|
|
8
10
|
/**
|
|
9
11
|
* @deprecated
|
|
10
12
|
* Use `on.error` instead.
|
package/dist/path-filter.d.ts
CHANGED
|
@@ -1,2 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import type { Filter } from './types';
|
|
3
|
+
import type * as http from 'http';
|
|
4
|
+
export declare function matchPathFilter<TReq = http.IncomingMessage>(pathFilter: Filter<TReq> | undefined, uri: string | undefined, req: http.IncomingMessage): boolean;
|
package/dist/path-filter.js
CHANGED
|
@@ -39,7 +39,7 @@ exports.matchPathFilter = matchPathFilter;
|
|
|
39
39
|
*/
|
|
40
40
|
function matchSingleStringPath(pathFilter, uri) {
|
|
41
41
|
const pathname = getUrlPathName(uri);
|
|
42
|
-
return pathname
|
|
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 (
|
|
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
|
}
|
|
@@ -5,10 +5,9 @@ const logger_1 = require("../../logger");
|
|
|
5
5
|
const loggerPlugin = (proxyServer, options) => {
|
|
6
6
|
const logger = (0, logger_1.getLogger)(options);
|
|
7
7
|
proxyServer.on('error', (err, req, res, target) => {
|
|
8
|
-
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
const targetHref = `${target === null || target === void 0 ? void 0 : target.href}`; // target is undefined when websocket errors
|
|
8
|
+
const hostname = req?.headers?.host;
|
|
9
|
+
const requestHref = `${hostname}${req?.url}`;
|
|
10
|
+
const targetHref = `${target?.href}`; // target is undefined when websocket errors
|
|
12
11
|
const errorMessage = '[HPM] Error occurred while proxying request %s to %s [%s] (%s)';
|
|
13
12
|
const errReference = 'https://nodejs.org/api/errors.html#errors_common_system_errors'; // link to Node Common Systems Errors page
|
|
14
13
|
logger.error(errorMessage, requestHref, targetHref, err.code || err, errReference);
|
|
@@ -21,9 +20,9 @@ const loggerPlugin = (proxyServer, options) => {
|
|
|
21
20
|
* ```
|
|
22
21
|
*/
|
|
23
22
|
proxyServer.on('proxyRes', (proxyRes, req, res) => {
|
|
24
|
-
var _a;
|
|
25
23
|
// BrowserSync uses req.originalUrl
|
|
26
|
-
|
|
24
|
+
// Next.js doesn't have req.baseUrl
|
|
25
|
+
const originalUrl = req.originalUrl ?? `${req.baseUrl || ''}${req.url}`;
|
|
27
26
|
const exchange = `[HPM] ${req.method} ${originalUrl} -> ${proxyRes.req.protocol}//${proxyRes.req.host}${proxyRes.req.path} [${proxyRes.statusCode}]`;
|
|
28
27
|
logger.info(exchange);
|
|
29
28
|
});
|
package/dist/types.d.ts
CHANGED
|
@@ -3,40 +3,57 @@
|
|
|
3
3
|
* https://github.com/DefinitelyTyped/DefinitelyTyped/blob/6f529c6c67a447190f86bfbf894d1061e41e07b7/types/http-proxy-middleware/index.d.ts
|
|
4
4
|
*/
|
|
5
5
|
/// <reference types="node" />
|
|
6
|
+
/// <reference types="node" />
|
|
7
|
+
/// <reference types="node" />
|
|
8
|
+
/// <reference types="node" />
|
|
6
9
|
import type * as http from 'http';
|
|
7
10
|
import type * as httpProxy from 'http-proxy';
|
|
8
11
|
import type * as net from 'net';
|
|
9
|
-
export
|
|
10
|
-
export
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
export type NextFunction<T = (err?: any) => void> = T;
|
|
13
|
+
export interface RequestHandler<TReq = http.IncomingMessage, TRes = http.ServerResponse, TNext = NextFunction> {
|
|
14
|
+
(req: TReq, res: TRes, next?: TNext): void | Promise<void>;
|
|
15
|
+
upgrade: (req: http.IncomingMessage, socket: net.Socket, head: Buffer) => void;
|
|
16
|
+
}
|
|
17
|
+
export type Filter<TReq = http.IncomingMessage> = string | string[] | ((pathname: string, req: TReq) => boolean);
|
|
18
|
+
export interface Plugin<TReq = http.IncomingMessage, TRes = http.ServerResponse> {
|
|
19
|
+
(proxyServer: httpProxy<TReq, TRes>, options: Options<TReq, TRes>): void;
|
|
15
20
|
}
|
|
16
|
-
export
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
proxyReqWs?: httpProxy.ProxyReqWsCallback;
|
|
22
|
-
proxyRes?: httpProxy.ProxyResCallback;
|
|
21
|
+
export interface OnProxyEvent<TReq = http.IncomingMessage, TRes = http.ServerResponse> {
|
|
22
|
+
error?: httpProxy.ErrorCallback<Error, TReq, TRes>;
|
|
23
|
+
proxyReq?: httpProxy.ProxyReqCallback<http.ClientRequest, TReq, TRes>;
|
|
24
|
+
proxyReqWs?: httpProxy.ProxyReqWsCallback<http.ClientRequest, TReq>;
|
|
25
|
+
proxyRes?: httpProxy.ProxyResCallback<TReq, TRes>;
|
|
23
26
|
open?: httpProxy.OpenCallback;
|
|
24
|
-
close?: httpProxy.CloseCallback
|
|
25
|
-
start?: httpProxy.StartCallback
|
|
26
|
-
end?: httpProxy.EndCallback
|
|
27
|
-
econnreset?: httpProxy.EconnresetCallback
|
|
28
|
-
}
|
|
29
|
-
export
|
|
30
|
-
export interface Options extends httpProxy.ServerOptions {
|
|
27
|
+
close?: httpProxy.CloseCallback<TReq>;
|
|
28
|
+
start?: httpProxy.StartCallback<TReq, TRes>;
|
|
29
|
+
end?: httpProxy.EndCallback<TReq, TRes>;
|
|
30
|
+
econnreset?: httpProxy.EconnresetCallback<Error, TReq, TRes>;
|
|
31
|
+
}
|
|
32
|
+
export type Logger = Pick<Console, 'info' | 'warn' | 'error'>;
|
|
33
|
+
export interface Options<TReq = http.IncomingMessage, TRes = http.ServerResponse> extends httpProxy.ServerOptions {
|
|
31
34
|
/**
|
|
32
35
|
* Narrow down requests to proxy or not.
|
|
33
36
|
* Filter on {@link http.IncomingMessage.url `pathname`} which is relative to the proxy's "mounting" point in the server.
|
|
34
37
|
* Or use the {@link http.IncomingMessage `req`} object for more complex filtering.
|
|
38
|
+
* @link https://github.com/chimurai/http-proxy-middleware/blob/master/recipes/pathFilter.md
|
|
39
|
+
* @since v3.0.0
|
|
40
|
+
*/
|
|
41
|
+
pathFilter?: Filter<TReq>;
|
|
42
|
+
/**
|
|
43
|
+
* Modify request paths before requests are send to the target.
|
|
44
|
+
* @example
|
|
45
|
+
* ```js
|
|
46
|
+
* createProxyMiddleware({
|
|
47
|
+
* pathRewrite: {
|
|
48
|
+
* '^/api/old-path': '/api/new-path', // rewrite path
|
|
49
|
+
* }
|
|
50
|
+
* });
|
|
51
|
+
* ```
|
|
52
|
+
* @link https://github.com/chimurai/http-proxy-middleware/blob/master/recipes/pathRewrite.md
|
|
35
53
|
*/
|
|
36
|
-
pathFilter?: Filter;
|
|
37
54
|
pathRewrite?: {
|
|
38
55
|
[regexp: string]: string;
|
|
39
|
-
} | ((path: string, req:
|
|
56
|
+
} | ((path: string, req: TReq) => string | undefined) | ((path: string, req: TReq) => Promise<string>);
|
|
40
57
|
/**
|
|
41
58
|
* Access the internal http-proxy server instance to customize behavior
|
|
42
59
|
*
|
|
@@ -50,12 +67,15 @@ export interface Options extends httpProxy.ServerOptions {
|
|
|
50
67
|
* }]
|
|
51
68
|
* });
|
|
52
69
|
* ```
|
|
70
|
+
* @link https://github.com/chimurai/http-proxy-middleware#plugins-array
|
|
71
|
+
* @since v3.0.0
|
|
53
72
|
*/
|
|
54
|
-
plugins?: Plugin[];
|
|
73
|
+
plugins?: Plugin<TReq, TRes>[];
|
|
55
74
|
/**
|
|
56
75
|
* Eject pre-configured plugins.
|
|
57
76
|
* NOTE: register your own error handlers to prevent server from crashing.
|
|
58
77
|
*
|
|
78
|
+
* @link https://github.com/chimurai/http-proxy-middleware#ejectplugins-boolean-default-false
|
|
59
79
|
* @since v3.0.0
|
|
60
80
|
*/
|
|
61
81
|
ejectPlugins?: boolean;
|
|
@@ -72,11 +92,25 @@ export interface Options extends httpProxy.ServerOptions {
|
|
|
72
92
|
* }
|
|
73
93
|
* });
|
|
74
94
|
* ```
|
|
95
|
+
* @link https://github.com/chimurai/http-proxy-middleware/blob/master/recipes/proxy-events.md
|
|
96
|
+
* @since v3.0.0
|
|
97
|
+
*/
|
|
98
|
+
on?: OnProxyEvent<TReq, TRes>;
|
|
99
|
+
/**
|
|
100
|
+
* Dynamically set the {@link Options.target `options.target`}.
|
|
101
|
+
* @example
|
|
102
|
+
* ```js
|
|
103
|
+
* createProxyMiddleware({
|
|
104
|
+
* router: async (req) => {
|
|
105
|
+
* return 'http://127:0.0.1:3000';
|
|
106
|
+
* }
|
|
107
|
+
* });
|
|
108
|
+
* ```
|
|
109
|
+
* @link https://github.com/chimurai/http-proxy-middleware/blob/master/recipes/router.md
|
|
75
110
|
*/
|
|
76
|
-
on?: OnProxyEvent;
|
|
77
111
|
router?: {
|
|
78
112
|
[hostOrPath: string]: httpProxy.ServerOptions['target'];
|
|
79
|
-
} | ((req:
|
|
113
|
+
} | ((req: TReq) => httpProxy.ServerOptions['target']) | ((req: TReq) => Promise<httpProxy.ServerOptions['target']>);
|
|
80
114
|
/**
|
|
81
115
|
* Log information from http-proxy-middleware
|
|
82
116
|
* @example
|
|
@@ -85,6 +119,8 @@ export interface Options extends httpProxy.ServerOptions {
|
|
|
85
119
|
* logger: console
|
|
86
120
|
* });
|
|
87
121
|
* ```
|
|
122
|
+
* @link https://github.com/chimurai/http-proxy-middleware/blob/master/recipes/logger.md
|
|
123
|
+
* @since v3.0.0
|
|
88
124
|
*/
|
|
89
125
|
logger?: Logger | any;
|
|
90
126
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "http-proxy-middleware",
|
|
3
|
-
"version": "3.0.0
|
|
3
|
+
"version": "3.0.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",
|
|
@@ -8,21 +8,18 @@
|
|
|
8
8
|
"dist"
|
|
9
9
|
],
|
|
10
10
|
"scripts": {
|
|
11
|
-
"clean": "rm -rf dist
|
|
11
|
+
"clean": "rm -rf dist coverage tsconfig.tsbuildinfo .eslintcache",
|
|
12
12
|
"lint": "yarn prettier && yarn eslint",
|
|
13
13
|
"lint:fix": "yarn prettier:fix && yarn eslint:fix",
|
|
14
|
-
"eslint": "eslint '{src,test}/**/*.ts'",
|
|
14
|
+
"eslint": "eslint '{src,test}/**/*.ts' --cache",
|
|
15
15
|
"eslint:fix": "yarn eslint --fix",
|
|
16
16
|
"prettier": "prettier --list-different \"**/*.{js,ts,md,yml,json,html}\"",
|
|
17
17
|
"prettier:fix": "prettier --write \"**/*.{js,ts,md,yml,json,html}\"",
|
|
18
|
-
"
|
|
19
|
-
"build": "tsc",
|
|
20
|
-
"pretest": "yarn build",
|
|
18
|
+
"build": "tsc --build",
|
|
21
19
|
"test": "jest",
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"prepack": "yarn build && rm dist/tsconfig.tsbuildinfo",
|
|
20
|
+
"coverage": "jest --coverage",
|
|
21
|
+
"prepare": "husky",
|
|
22
|
+
"prepack": "yarn clean && yarn test && yarn build",
|
|
26
23
|
"spellcheck": "npx --yes cspell --show-context --show-suggestions '**/*.*'"
|
|
27
24
|
},
|
|
28
25
|
"repository": {
|
|
@@ -54,58 +51,47 @@
|
|
|
54
51
|
},
|
|
55
52
|
"homepage": "https://github.com/chimurai/http-proxy-middleware#readme",
|
|
56
53
|
"devDependencies": {
|
|
57
|
-
"@commitlint/cli": "
|
|
58
|
-
"@commitlint/config-conventional": "
|
|
59
|
-
"@types/debug": "4.1.
|
|
60
|
-
"@types/express": "4.17.
|
|
61
|
-
"@types/is-glob": "4.0.
|
|
62
|
-
"@types/jest": "
|
|
63
|
-
"@types/micromatch": "4.0.
|
|
64
|
-
"@types/node": "
|
|
54
|
+
"@commitlint/cli": "17.7.1",
|
|
55
|
+
"@commitlint/config-conventional": "17.7.0",
|
|
56
|
+
"@types/debug": "4.1.12",
|
|
57
|
+
"@types/express": "4.17.21",
|
|
58
|
+
"@types/is-glob": "4.0.4",
|
|
59
|
+
"@types/jest": "29.5.12",
|
|
60
|
+
"@types/micromatch": "4.0.6",
|
|
61
|
+
"@types/node": "20.11.30",
|
|
65
62
|
"@types/supertest": "2.0.12",
|
|
66
|
-
"@types/ws": "8.5.
|
|
67
|
-
"@typescript-eslint/eslint-plugin": "
|
|
68
|
-
"@typescript-eslint/parser": "
|
|
69
|
-
"body-parser": "1.20.
|
|
70
|
-
"browser-sync": "
|
|
63
|
+
"@types/ws": "8.5.10",
|
|
64
|
+
"@typescript-eslint/eslint-plugin": "7.4.0",
|
|
65
|
+
"@typescript-eslint/parser": "7.4.0",
|
|
66
|
+
"body-parser": "1.20.2",
|
|
67
|
+
"browser-sync": "3.0.2",
|
|
71
68
|
"connect": "3.7.0",
|
|
72
|
-
"eslint": "8.
|
|
73
|
-
"eslint-config-prettier": "
|
|
74
|
-
"eslint-plugin-prettier": "
|
|
75
|
-
"express": "4.
|
|
69
|
+
"eslint": "8.57.0",
|
|
70
|
+
"eslint-config-prettier": "9.1.0",
|
|
71
|
+
"eslint-plugin-prettier": "5.1.3",
|
|
72
|
+
"express": "4.19.2",
|
|
76
73
|
"get-port": "5.1.1",
|
|
77
|
-
"husky": "
|
|
78
|
-
"jest": "
|
|
79
|
-
"lint-staged": "
|
|
80
|
-
"mockttp": "
|
|
81
|
-
"open": "8.4.
|
|
82
|
-
"prettier": "2.
|
|
83
|
-
"supertest": "6.
|
|
84
|
-
"ts-jest": "
|
|
85
|
-
"typescript": "4.
|
|
86
|
-
"ws": "8.
|
|
74
|
+
"husky": "9.0.11",
|
|
75
|
+
"jest": "29.7.0",
|
|
76
|
+
"lint-staged": "15.2.2",
|
|
77
|
+
"mockttp": "3.10.1",
|
|
78
|
+
"open": "8.4.2",
|
|
79
|
+
"prettier": "3.2.5",
|
|
80
|
+
"supertest": "6.3.4",
|
|
81
|
+
"ts-jest": "29.1.2",
|
|
82
|
+
"typescript": "5.4.3",
|
|
83
|
+
"ws": "8.16.0"
|
|
87
84
|
},
|
|
88
85
|
"dependencies": {
|
|
89
|
-
"@types/http-proxy": "^1.17.
|
|
86
|
+
"@types/http-proxy": "^1.17.10",
|
|
90
87
|
"debug": "^4.3.4",
|
|
91
88
|
"http-proxy": "^1.18.1",
|
|
92
89
|
"is-glob": "^4.0.1",
|
|
93
90
|
"is-plain-obj": "^3.0.0",
|
|
94
91
|
"micromatch": "^4.0.5"
|
|
95
92
|
},
|
|
96
|
-
"peerDependencies": {
|
|
97
|
-
"@types/express": "^4.17.13"
|
|
98
|
-
},
|
|
99
|
-
"peerDependenciesMeta": {
|
|
100
|
-
"@types/express": {
|
|
101
|
-
"optional": true
|
|
102
|
-
}
|
|
103
|
-
},
|
|
104
|
-
"resolutions": {
|
|
105
|
-
"browser-sync/portscanner": "2.2.0"
|
|
106
|
-
},
|
|
107
93
|
"engines": {
|
|
108
|
-
"node": ">=
|
|
94
|
+
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
|
|
109
95
|
},
|
|
110
96
|
"commitlint": {
|
|
111
97
|
"extends": [
|