http-proxy-middleware 2.0.6 → 3.0.0-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 +254 -198
- package/dist/configuration.d.ts +2 -0
- package/dist/configuration.js +10 -0
- package/dist/debug.d.ts +5 -0
- package/dist/debug.js +8 -0
- package/dist/errors.d.ts +1 -1
- package/dist/errors.js +1 -1
- package/dist/get-plugins.d.ts +2 -0
- package/dist/get-plugins.js +15 -0
- package/dist/handlers/fix-request-body.d.ts +2 -1
- package/dist/handlers/index.js +5 -1
- package/dist/handlers/response-interceptor.js +10 -1
- package/dist/http-proxy-middleware.d.ts +3 -10
- package/dist/http-proxy-middleware.js +39 -50
- package/dist/index.d.ts +11 -3
- package/dist/index.js +15 -3
- package/dist/legacy/create-proxy-middleware.d.ts +11 -0
- package/dist/legacy/create-proxy-middleware.js +17 -0
- package/dist/legacy/index.d.ts +1 -0
- package/dist/legacy/index.js +17 -0
- package/dist/legacy/options-adapter.d.ts +6 -0
- package/dist/legacy/options-adapter.js +92 -0
- package/dist/legacy/public.d.ts +2 -0
- package/dist/legacy/public.js +5 -0
- package/dist/legacy/types.d.ts +110 -0
- package/dist/legacy/types.js +2 -0
- package/dist/logger.d.ts +2 -14
- package/dist/logger.js +20 -129
- package/dist/path-filter.d.ts +2 -0
- package/dist/{context-matcher.js → path-filter.js} +24 -24
- package/dist/path-rewriter.js +6 -6
- package/dist/plugins/default/debug-proxy-errors-plugin.d.ts +6 -0
- package/dist/plugins/default/debug-proxy-errors-plugin.js +61 -0
- package/dist/plugins/default/error-response-plugin.d.ts +2 -0
- package/dist/plugins/default/error-response-plugin.js +19 -0
- package/dist/plugins/default/index.d.ts +4 -0
- package/dist/plugins/default/index.js +20 -0
- package/dist/plugins/default/logger-plugin.d.ts +2 -0
- package/dist/plugins/default/logger-plugin.js +43 -0
- package/dist/plugins/default/proxy-events.d.ts +22 -0
- package/dist/plugins/default/proxy-events.js +33 -0
- package/dist/router.js +7 -7
- package/dist/status-code.d.ts +1 -0
- package/dist/status-code.js +24 -0
- package/dist/types.d.ts +71 -35
- package/dist/utils/function.d.ts +1 -0
- package/dist/utils/function.js +8 -0
- package/package.json +25 -19
- package/dist/_handlers.d.ts +0 -4
- package/dist/_handlers.js +0 -84
- package/dist/config-factory.d.ts +0 -6
- package/dist/config-factory.js +0 -80
- package/dist/context-matcher.d.ts +0 -2
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { Options } from '..';
|
|
2
|
+
/**
|
|
3
|
+
* @deprecated
|
|
4
|
+
*
|
|
5
|
+
* Will be removed in a future version.
|
|
6
|
+
*/
|
|
7
|
+
export interface LegacyOptions extends Options {
|
|
8
|
+
/**
|
|
9
|
+
* @deprecated
|
|
10
|
+
* Use `on.error` instead.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```js
|
|
14
|
+
* {
|
|
15
|
+
* on: {
|
|
16
|
+
* error: () => {}
|
|
17
|
+
* }
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
onError?: (...args: any[]) => void;
|
|
21
|
+
/**
|
|
22
|
+
* @deprecated
|
|
23
|
+
* Use `on.proxyRes` instead.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```js
|
|
27
|
+
* {
|
|
28
|
+
* on: {
|
|
29
|
+
* proxyRes: () => {}
|
|
30
|
+
* }
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
onProxyRes?: (...args: any[]) => void;
|
|
34
|
+
/**
|
|
35
|
+
* @deprecated
|
|
36
|
+
* Use `on.proxyReq` instead.
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```js
|
|
40
|
+
* {
|
|
41
|
+
* on: {
|
|
42
|
+
* proxyReq: () => {}
|
|
43
|
+
* }
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
onProxyReq?: (...args: any[]) => void;
|
|
47
|
+
/**
|
|
48
|
+
* @deprecated
|
|
49
|
+
* Use `on.proxyReqWs` instead.
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```js
|
|
53
|
+
* {
|
|
54
|
+
* on: {
|
|
55
|
+
* proxyReqWs: () => {}
|
|
56
|
+
* }
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
onProxyReqWs?: (...args: any[]) => void;
|
|
60
|
+
/**
|
|
61
|
+
* @deprecated
|
|
62
|
+
* Use `on.open` instead.
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* ```js
|
|
66
|
+
* {
|
|
67
|
+
* on: {
|
|
68
|
+
* open: () => {}
|
|
69
|
+
* }
|
|
70
|
+
* ```
|
|
71
|
+
*/
|
|
72
|
+
onOpen?: (...args: any[]) => void;
|
|
73
|
+
/**
|
|
74
|
+
* @deprecated
|
|
75
|
+
* Use `on.close` instead.
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* ```js
|
|
79
|
+
* {
|
|
80
|
+
* on: {
|
|
81
|
+
* close: () => {}
|
|
82
|
+
* }
|
|
83
|
+
* ```
|
|
84
|
+
*/
|
|
85
|
+
onClose?: (...args: any[]) => void;
|
|
86
|
+
/**
|
|
87
|
+
* @deprecated
|
|
88
|
+
* Use `logger` instead.
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* ```js
|
|
92
|
+
* {
|
|
93
|
+
* logger: console
|
|
94
|
+
* }
|
|
95
|
+
* ```
|
|
96
|
+
*/
|
|
97
|
+
logProvider?: any;
|
|
98
|
+
/**
|
|
99
|
+
* @deprecated
|
|
100
|
+
* Use `logger` instead.
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* ```js
|
|
104
|
+
* {
|
|
105
|
+
* logger: console
|
|
106
|
+
* }
|
|
107
|
+
* ```
|
|
108
|
+
*/
|
|
109
|
+
logLevel?: any;
|
|
110
|
+
}
|
package/dist/logger.d.ts
CHANGED
|
@@ -1,14 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
* -> normal proxy
|
|
4
|
-
* => router
|
|
5
|
-
* ~> pathRewrite
|
|
6
|
-
* ≈> router + pathRewrite
|
|
7
|
-
*
|
|
8
|
-
* @param {String} originalPath
|
|
9
|
-
* @param {String} newPath
|
|
10
|
-
* @param {String} originalTarget
|
|
11
|
-
* @param {String} newTarget
|
|
12
|
-
* @return {String}
|
|
13
|
-
*/
|
|
14
|
-
export declare function getArrow(originalPath: any, newPath: any, originalTarget: any, newTarget: any): string;
|
|
1
|
+
import { Logger, Options } from './types';
|
|
2
|
+
export declare function getLogger(options: Options): Logger;
|
package/dist/logger.js
CHANGED
|
@@ -1,135 +1,26 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
/* eslint-disable
|
|
2
|
+
/* eslint-disable @typescript-eslint/no-empty-function */
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.
|
|
5
|
-
const util = require("util");
|
|
6
|
-
let loggerInstance;
|
|
7
|
-
const defaultProvider = {
|
|
8
|
-
// tslint:disable: no-console
|
|
9
|
-
log: console.log,
|
|
10
|
-
debug: console.log,
|
|
11
|
-
info: console.info,
|
|
12
|
-
warn: console.warn,
|
|
13
|
-
error: console.error,
|
|
14
|
-
};
|
|
15
|
-
// log level 'weight'
|
|
16
|
-
var LEVELS;
|
|
17
|
-
(function (LEVELS) {
|
|
18
|
-
LEVELS[LEVELS["debug"] = 10] = "debug";
|
|
19
|
-
LEVELS[LEVELS["info"] = 20] = "info";
|
|
20
|
-
LEVELS[LEVELS["warn"] = 30] = "warn";
|
|
21
|
-
LEVELS[LEVELS["error"] = 50] = "error";
|
|
22
|
-
LEVELS[LEVELS["silent"] = 80] = "silent";
|
|
23
|
-
})(LEVELS || (LEVELS = {}));
|
|
24
|
-
function getInstance() {
|
|
25
|
-
if (!loggerInstance) {
|
|
26
|
-
loggerInstance = new Logger();
|
|
27
|
-
}
|
|
28
|
-
return loggerInstance;
|
|
29
|
-
}
|
|
30
|
-
exports.getInstance = getInstance;
|
|
31
|
-
class Logger {
|
|
32
|
-
constructor() {
|
|
33
|
-
this.setLevel('info');
|
|
34
|
-
this.setProvider(() => defaultProvider);
|
|
35
|
-
}
|
|
36
|
-
// log will log messages, regardless of logLevels
|
|
37
|
-
log() {
|
|
38
|
-
this.provider.log(this._interpolate.apply(null, arguments));
|
|
39
|
-
}
|
|
40
|
-
debug() {
|
|
41
|
-
if (this._showLevel('debug')) {
|
|
42
|
-
this.provider.debug(this._interpolate.apply(null, arguments));
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
info() {
|
|
46
|
-
if (this._showLevel('info')) {
|
|
47
|
-
this.provider.info(this._interpolate.apply(null, arguments));
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
warn() {
|
|
51
|
-
if (this._showLevel('warn')) {
|
|
52
|
-
this.provider.warn(this._interpolate.apply(null, arguments));
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
error() {
|
|
56
|
-
if (this._showLevel('error')) {
|
|
57
|
-
this.provider.error(this._interpolate.apply(null, arguments));
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
setLevel(v) {
|
|
61
|
-
if (this.isValidLevel(v)) {
|
|
62
|
-
this.logLevel = v;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
setProvider(fn) {
|
|
66
|
-
if (fn && this.isValidProvider(fn)) {
|
|
67
|
-
this.provider = fn(defaultProvider);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
isValidProvider(fnProvider) {
|
|
71
|
-
const result = true;
|
|
72
|
-
if (fnProvider && typeof fnProvider !== 'function') {
|
|
73
|
-
throw new Error('[HPM] Log provider config error. Expecting a function.');
|
|
74
|
-
}
|
|
75
|
-
return result;
|
|
76
|
-
}
|
|
77
|
-
isValidLevel(levelName) {
|
|
78
|
-
const validLevels = Object.keys(LEVELS);
|
|
79
|
-
const isValid = validLevels.includes(levelName);
|
|
80
|
-
if (!isValid) {
|
|
81
|
-
throw new Error('[HPM] Log level error. Invalid logLevel.');
|
|
82
|
-
}
|
|
83
|
-
return isValid;
|
|
84
|
-
}
|
|
85
|
-
/**
|
|
86
|
-
* Decide to log or not to log, based on the log levels 'weight'
|
|
87
|
-
* @param {String} showLevel [debug, info, warn, error, silent]
|
|
88
|
-
* @return {Boolean}
|
|
89
|
-
*/
|
|
90
|
-
_showLevel(showLevel) {
|
|
91
|
-
let result = false;
|
|
92
|
-
const currentLogLevel = LEVELS[this.logLevel];
|
|
93
|
-
if (currentLogLevel && currentLogLevel <= LEVELS[showLevel]) {
|
|
94
|
-
result = true;
|
|
95
|
-
}
|
|
96
|
-
return result;
|
|
97
|
-
}
|
|
98
|
-
// make sure logged messages and its data are return interpolated
|
|
99
|
-
// make it possible for additional log data, such date/time or custom prefix.
|
|
100
|
-
_interpolate(format, ...args) {
|
|
101
|
-
const result = util.format(format, ...args);
|
|
102
|
-
return result;
|
|
103
|
-
}
|
|
104
|
-
}
|
|
4
|
+
exports.getLogger = void 0;
|
|
105
5
|
/**
|
|
106
|
-
*
|
|
107
|
-
* => router
|
|
108
|
-
* ~> pathRewrite
|
|
109
|
-
* ≈> router + pathRewrite
|
|
6
|
+
* Compatibility matrix
|
|
110
7
|
*
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
8
|
+
| Library | log | info | warn | error | \<interpolation\> |
|
|
9
|
+
|----------|:------|:-------|:------|:--------|:------------------|
|
|
10
|
+
| console | ✅ | ✅ | ✅ | ✅ | ✅ (%s %o %O) |
|
|
11
|
+
| bunyan | ❌ | ✅ | ✅ | ✅ | ✅ (%s %o %O) |
|
|
12
|
+
| pino | ❌ | ✅ | ✅ | ✅ | ✅ (%s %o %O) |
|
|
13
|
+
| winston | ❌ | ✅ | ✅ | ✅ | ✅ (%s %o %O)^1 |
|
|
14
|
+
| log4js | ❌ | ✅ | ✅ | ✅ | ✅ (%s %o %O) |
|
|
15
|
+
*
|
|
16
|
+
* ^1: https://github.com/winstonjs/winston#string-interpolation
|
|
116
17
|
*/
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
else if (!isNewPath && isNewTarget) {
|
|
125
|
-
arrow.unshift('=');
|
|
126
|
-
}
|
|
127
|
-
else if (isNewPath && isNewTarget) {
|
|
128
|
-
arrow.unshift('≈');
|
|
129
|
-
}
|
|
130
|
-
else {
|
|
131
|
-
arrow.unshift('-');
|
|
132
|
-
}
|
|
133
|
-
return arrow.join('');
|
|
18
|
+
const noopLogger = {
|
|
19
|
+
info: () => { },
|
|
20
|
+
warn: () => { },
|
|
21
|
+
error: () => { },
|
|
22
|
+
};
|
|
23
|
+
function getLogger(options) {
|
|
24
|
+
return options.logger || noopLogger;
|
|
134
25
|
}
|
|
135
|
-
exports.
|
|
26
|
+
exports.getLogger = getLogger;
|
|
@@ -1,45 +1,45 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.matchPathFilter = void 0;
|
|
4
4
|
const isGlob = require("is-glob");
|
|
5
5
|
const micromatch = require("micromatch");
|
|
6
6
|
const url = require("url");
|
|
7
7
|
const errors_1 = require("./errors");
|
|
8
|
-
function
|
|
8
|
+
function matchPathFilter(pathFilter = '/', uri, req) {
|
|
9
9
|
// single path
|
|
10
|
-
if (isStringPath(
|
|
11
|
-
return matchSingleStringPath(
|
|
10
|
+
if (isStringPath(pathFilter)) {
|
|
11
|
+
return matchSingleStringPath(pathFilter, uri);
|
|
12
12
|
}
|
|
13
13
|
// single glob path
|
|
14
|
-
if (isGlobPath(
|
|
15
|
-
return matchSingleGlobPath(
|
|
14
|
+
if (isGlobPath(pathFilter)) {
|
|
15
|
+
return matchSingleGlobPath(pathFilter, uri);
|
|
16
16
|
}
|
|
17
17
|
// multi path
|
|
18
|
-
if (Array.isArray(
|
|
19
|
-
if (
|
|
20
|
-
return matchMultiPath(
|
|
18
|
+
if (Array.isArray(pathFilter)) {
|
|
19
|
+
if (pathFilter.every(isStringPath)) {
|
|
20
|
+
return matchMultiPath(pathFilter, uri);
|
|
21
21
|
}
|
|
22
|
-
if (
|
|
23
|
-
return matchMultiGlobPath(
|
|
22
|
+
if (pathFilter.every(isGlobPath)) {
|
|
23
|
+
return matchMultiGlobPath(pathFilter, uri);
|
|
24
24
|
}
|
|
25
25
|
throw new Error(errors_1.ERRORS.ERR_CONTEXT_MATCHER_INVALID_ARRAY);
|
|
26
26
|
}
|
|
27
27
|
// custom matching
|
|
28
|
-
if (typeof
|
|
28
|
+
if (typeof pathFilter === 'function') {
|
|
29
29
|
const pathname = getUrlPathName(uri);
|
|
30
|
-
return
|
|
30
|
+
return pathFilter(pathname, req);
|
|
31
31
|
}
|
|
32
32
|
throw new Error(errors_1.ERRORS.ERR_CONTEXT_MATCHER_GENERIC);
|
|
33
33
|
}
|
|
34
|
-
exports.
|
|
34
|
+
exports.matchPathFilter = matchPathFilter;
|
|
35
35
|
/**
|
|
36
|
-
* @param {String}
|
|
36
|
+
* @param {String} pathFilter '/api'
|
|
37
37
|
* @param {String} uri 'http://example.org/api/b/c/d.html'
|
|
38
38
|
* @return {Boolean}
|
|
39
39
|
*/
|
|
40
|
-
function matchSingleStringPath(
|
|
40
|
+
function matchSingleStringPath(pathFilter, uri) {
|
|
41
41
|
const pathname = getUrlPathName(uri);
|
|
42
|
-
return pathname.indexOf(
|
|
42
|
+
return pathname.indexOf(pathFilter) === 0;
|
|
43
43
|
}
|
|
44
44
|
function matchSingleGlobPath(pattern, uri) {
|
|
45
45
|
const pathname = getUrlPathName(uri);
|
|
@@ -50,13 +50,13 @@ function matchMultiGlobPath(patternList, uri) {
|
|
|
50
50
|
return matchSingleGlobPath(patternList, uri);
|
|
51
51
|
}
|
|
52
52
|
/**
|
|
53
|
-
* @param {String}
|
|
53
|
+
* @param {String} pathFilterList ['/api', '/ajax']
|
|
54
54
|
* @param {String} uri 'http://example.org/api/b/c/d.html'
|
|
55
55
|
* @return {Boolean}
|
|
56
56
|
*/
|
|
57
|
-
function matchMultiPath(
|
|
57
|
+
function matchMultiPath(pathFilterList, uri) {
|
|
58
58
|
let isMultiPath = false;
|
|
59
|
-
for (const context of
|
|
59
|
+
for (const context of pathFilterList) {
|
|
60
60
|
if (matchSingleStringPath(context, uri)) {
|
|
61
61
|
isMultiPath = true;
|
|
62
62
|
break;
|
|
@@ -73,9 +73,9 @@ function matchMultiPath(contextList, uri) {
|
|
|
73
73
|
function getUrlPathName(uri) {
|
|
74
74
|
return uri && url.parse(uri).pathname;
|
|
75
75
|
}
|
|
76
|
-
function isStringPath(
|
|
77
|
-
return typeof
|
|
76
|
+
function isStringPath(pathFilter) {
|
|
77
|
+
return typeof pathFilter === 'string' && !isGlob(pathFilter);
|
|
78
78
|
}
|
|
79
|
-
function isGlobPath(
|
|
80
|
-
return isGlob(
|
|
79
|
+
function isGlobPath(pathFilter) {
|
|
80
|
+
return isGlob(pathFilter);
|
|
81
81
|
}
|
package/dist/path-rewriter.js
CHANGED
|
@@ -3,8 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.createPathRewriter = void 0;
|
|
4
4
|
const isPlainObj = require("is-plain-obj");
|
|
5
5
|
const errors_1 = require("./errors");
|
|
6
|
-
const
|
|
7
|
-
const
|
|
6
|
+
const debug_1 = require("./debug");
|
|
7
|
+
const debug = debug_1.Debug.extend('path-rewriter');
|
|
8
8
|
/**
|
|
9
9
|
* Create rewrite function, to cache parsed rewrite rules.
|
|
10
10
|
*
|
|
@@ -29,7 +29,7 @@ function createPathRewriter(rewriteConfig) {
|
|
|
29
29
|
for (const rule of rulesCache) {
|
|
30
30
|
if (rule.regex.test(path)) {
|
|
31
31
|
result = result.replace(rule.regex, rule.value);
|
|
32
|
-
|
|
32
|
+
debug('rewriting path from "%s" to "%s"', path, result);
|
|
33
33
|
break;
|
|
34
34
|
}
|
|
35
35
|
}
|
|
@@ -54,12 +54,12 @@ function isValidRewriteConfig(rewriteConfig) {
|
|
|
54
54
|
function parsePathRewriteRules(rewriteConfig) {
|
|
55
55
|
const rules = [];
|
|
56
56
|
if (isPlainObj(rewriteConfig)) {
|
|
57
|
-
for (const [key] of Object.entries(rewriteConfig)) {
|
|
57
|
+
for (const [key, value] of Object.entries(rewriteConfig)) {
|
|
58
58
|
rules.push({
|
|
59
59
|
regex: new RegExp(key),
|
|
60
|
-
value:
|
|
60
|
+
value: value,
|
|
61
61
|
});
|
|
62
|
-
|
|
62
|
+
debug('rewrite rule created: "%s" ~> "%s"', key, value);
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
return rules;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { Plugin } from '../../types';
|
|
2
|
+
/**
|
|
3
|
+
* Subscribe to {@link https://www.npmjs.com/package/http-proxy#listening-for-proxy-events http-proxy error events} to prevent server from crashing.
|
|
4
|
+
* Errors are logged with {@link https://www.npmjs.com/package/debug debug} library.
|
|
5
|
+
*/
|
|
6
|
+
export declare const debugProxyErrorsPlugin: Plugin;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.debugProxyErrorsPlugin = void 0;
|
|
4
|
+
const debug_1 = require("../../debug");
|
|
5
|
+
const debug = debug_1.Debug.extend('debug-proxy-errors-plugin');
|
|
6
|
+
/**
|
|
7
|
+
* Subscribe to {@link https://www.npmjs.com/package/http-proxy#listening-for-proxy-events http-proxy error events} to prevent server from crashing.
|
|
8
|
+
* Errors are logged with {@link https://www.npmjs.com/package/debug debug} library.
|
|
9
|
+
*/
|
|
10
|
+
const debugProxyErrorsPlugin = (proxyServer) => {
|
|
11
|
+
/**
|
|
12
|
+
* http-proxy doesn't handle any errors by default (https://github.com/http-party/node-http-proxy#listening-for-proxy-events)
|
|
13
|
+
* Prevent server from crashing when http-proxy errors (uncaught errors)
|
|
14
|
+
*/
|
|
15
|
+
proxyServer.on('error', (error, req, res, target) => {
|
|
16
|
+
debug(`http-proxy error event: \n%O`, error);
|
|
17
|
+
});
|
|
18
|
+
proxyServer.on('proxyReq', (proxyReq, req, socket) => {
|
|
19
|
+
socket.on('error', (error) => {
|
|
20
|
+
debug('Socket error in proxyReq event: \n%O', error);
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
/**
|
|
24
|
+
* Fix SSE close events
|
|
25
|
+
* @link https://github.com/chimurai/http-proxy-middleware/issues/678
|
|
26
|
+
* @link https://github.com/http-party/node-http-proxy/issues/1520#issue-877626125
|
|
27
|
+
*/
|
|
28
|
+
proxyServer.on('proxyRes', (proxyRes, req, res) => {
|
|
29
|
+
res.on('close', () => {
|
|
30
|
+
if (!res.writableEnded) {
|
|
31
|
+
debug('Destroying proxyRes in proxyRes close event');
|
|
32
|
+
proxyRes.destroy();
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
/**
|
|
37
|
+
* Fix crash when target server restarts
|
|
38
|
+
* https://github.com/chimurai/http-proxy-middleware/issues/476#issuecomment-746329030
|
|
39
|
+
* https://github.com/webpack/webpack-dev-server/issues/1642#issuecomment-790602225
|
|
40
|
+
*/
|
|
41
|
+
proxyServer.on('proxyReqWs', (proxyReq, req, socket) => {
|
|
42
|
+
socket.on('error', (error) => {
|
|
43
|
+
debug('Socket error in proxyReqWs event: \n%O', error);
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
proxyServer.on('open', (proxySocket) => {
|
|
47
|
+
proxySocket.on('error', (error) => {
|
|
48
|
+
debug('Socket error in open event: \n%O', error);
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
proxyServer.on('close', (req, socket, head) => {
|
|
52
|
+
socket.on('error', (error) => {
|
|
53
|
+
debug('Socket error in close event: \n%O', error);
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
// https://github.com/webpack/webpack-dev-server/issues/1642#issuecomment-1103136590
|
|
57
|
+
proxyServer.on('econnreset', (error, req, res, target) => {
|
|
58
|
+
debug(`http-proxy econnreset event: \n%O`, error);
|
|
59
|
+
});
|
|
60
|
+
};
|
|
61
|
+
exports.debugProxyErrorsPlugin = debugProxyErrorsPlugin;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.errorResponsePlugin = void 0;
|
|
4
|
+
const status_code_1 = require("../../status-code");
|
|
5
|
+
const errorResponsePlugin = (proxyServer, options) => {
|
|
6
|
+
proxyServer.on('error', (err, req, res, target) => {
|
|
7
|
+
// Re-throw error. Not recoverable since req & res are empty.
|
|
8
|
+
if (!req && !res) {
|
|
9
|
+
throw err; // "Error: Must provide a proper URL as target"
|
|
10
|
+
}
|
|
11
|
+
if (res.writeHead && !res.headersSent) {
|
|
12
|
+
const statusCode = (0, status_code_1.getStatusCode)(err.code);
|
|
13
|
+
res.writeHead(statusCode);
|
|
14
|
+
}
|
|
15
|
+
const host = req.headers && req.headers.host;
|
|
16
|
+
res.end(`Error occurred while trying to proxy: ${host}${req.url}`);
|
|
17
|
+
});
|
|
18
|
+
};
|
|
19
|
+
exports.errorResponsePlugin = errorResponsePlugin;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./debug-proxy-errors-plugin"), exports);
|
|
18
|
+
__exportStar(require("./error-response-plugin"), exports);
|
|
19
|
+
__exportStar(require("./logger-plugin"), exports);
|
|
20
|
+
__exportStar(require("./proxy-events"), exports);
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.loggerPlugin = void 0;
|
|
4
|
+
const logger_1 = require("../../logger");
|
|
5
|
+
const loggerPlugin = (proxyServer, options) => {
|
|
6
|
+
const logger = (0, logger_1.getLogger)(options);
|
|
7
|
+
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
|
|
12
|
+
const errorMessage = '[HPM] Error occurred while proxying request %s to %s [%s] (%s)';
|
|
13
|
+
const errReference = 'https://nodejs.org/api/errors.html#errors_common_system_errors'; // link to Node Common Systems Errors page
|
|
14
|
+
logger.error(errorMessage, requestHref, targetHref, err.code || err, errReference);
|
|
15
|
+
});
|
|
16
|
+
/**
|
|
17
|
+
* Log request and response
|
|
18
|
+
* @example
|
|
19
|
+
* ```shell
|
|
20
|
+
* [HPM] GET /users/ -> http://jsonplaceholder.typicode.com/users/ [304]
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
proxyServer.on('proxyRes', (proxyRes, req, res) => {
|
|
24
|
+
var _a;
|
|
25
|
+
// BrowserSync uses req.originalUrl
|
|
26
|
+
const originalUrl = (_a = req.originalUrl) !== null && _a !== void 0 ? _a : `${req.baseUrl}${req.path}`;
|
|
27
|
+
const exchange = `[HPM] ${req.method} ${originalUrl} -> ${proxyRes.req.protocol}//${proxyRes.req.host}${proxyRes.req.path} [${proxyRes.statusCode}]`;
|
|
28
|
+
logger.info(exchange);
|
|
29
|
+
});
|
|
30
|
+
/**
|
|
31
|
+
* When client opens WebSocket connection
|
|
32
|
+
*/
|
|
33
|
+
proxyServer.on('open', (socket) => {
|
|
34
|
+
logger.info('[HPM] Client connected: %o', socket.address());
|
|
35
|
+
});
|
|
36
|
+
/**
|
|
37
|
+
* When client closes WebSocket connection
|
|
38
|
+
*/
|
|
39
|
+
proxyServer.on('close', (req, proxySocket, proxyHead) => {
|
|
40
|
+
logger.info('[HPM] Client disconnected: %o', proxySocket.address());
|
|
41
|
+
});
|
|
42
|
+
};
|
|
43
|
+
exports.loggerPlugin = loggerPlugin;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Plugin } from '../../types';
|
|
2
|
+
/**
|
|
3
|
+
* Implements option.on object to subscribe to http-proxy events.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```js
|
|
7
|
+
* createProxyMiddleware({
|
|
8
|
+
* on: {
|
|
9
|
+
* error: (error, req, res, target) => {},
|
|
10
|
+
* proxyReq: (proxyReq, req, res, options) => {},
|
|
11
|
+
* proxyReqWs: (proxyReq, req, socket, options) => {},
|
|
12
|
+
* proxyRes: (proxyRes, req, res) => {},
|
|
13
|
+
* open: (proxySocket) => {},
|
|
14
|
+
* close: (proxyRes, proxySocket, proxyHead) => {},
|
|
15
|
+
* start: (req, res, target) => {},
|
|
16
|
+
* end: (req, res, proxyRes) => {},
|
|
17
|
+
* econnreset: (error, req, res, target) => {},
|
|
18
|
+
* }
|
|
19
|
+
* });
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export declare const proxyEventsPlugin: Plugin;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.proxyEventsPlugin = void 0;
|
|
4
|
+
const debug_1 = require("../../debug");
|
|
5
|
+
const function_1 = require("../../utils/function");
|
|
6
|
+
const debug = debug_1.Debug.extend('proxy-events-plugin');
|
|
7
|
+
/**
|
|
8
|
+
* Implements option.on object to subscribe to http-proxy events.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```js
|
|
12
|
+
* createProxyMiddleware({
|
|
13
|
+
* on: {
|
|
14
|
+
* error: (error, req, res, target) => {},
|
|
15
|
+
* proxyReq: (proxyReq, req, res, options) => {},
|
|
16
|
+
* proxyReqWs: (proxyReq, req, socket, options) => {},
|
|
17
|
+
* proxyRes: (proxyRes, req, res) => {},
|
|
18
|
+
* open: (proxySocket) => {},
|
|
19
|
+
* close: (proxyRes, proxySocket, proxyHead) => {},
|
|
20
|
+
* start: (req, res, target) => {},
|
|
21
|
+
* end: (req, res, proxyRes) => {},
|
|
22
|
+
* econnreset: (error, req, res, target) => {},
|
|
23
|
+
* }
|
|
24
|
+
* });
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
const proxyEventsPlugin = (proxyServer, options) => {
|
|
28
|
+
Object.entries(options.on || {}).forEach(([eventName, handler]) => {
|
|
29
|
+
debug(`register event handler: "${eventName}" -> "${(0, function_1.getFunctionName)(handler)}"`);
|
|
30
|
+
proxyServer.on(eventName, handler);
|
|
31
|
+
});
|
|
32
|
+
};
|
|
33
|
+
exports.proxyEventsPlugin = proxyEventsPlugin;
|