Skip to content

Commit 8c7ef76

Browse files
committed
refactor(handlers): refactor to plugins [BREAKING CHANGE] (#745)
* feat(debug): debug proxy server errors * refactor(handlers): migrate error, response and log handlers to plugins [BREAKING CHANGE] * refactor(proxy events): refactor to proxy-events plugin [BREAKING CHANGE]
1 parent ef5c844 commit 8c7ef76

22 files changed

+401
-403
lines changed

README.md

+26-9
Original file line numberDiff line numberDiff line change
@@ -274,8 +274,8 @@ router: async function(req) {
274274
### `plugins` (Array)
275275

276276
```js
277-
const simpleRequestLogger = (proxy, options) => {
278-
proxy.on('proxyReq', (proxyReq, req, res) => {
277+
const simpleRequestLogger = (proxyServer, options) => {
278+
proxyServer.on('proxyReq', (proxyReq, req, res) => {
279279
console.log(`[HPM] [${req.method}] ${req.url}`); // outputs: [HPM] GET /users
280280
});
281281
},
@@ -323,9 +323,26 @@ function logProvider(provider) {
323323

324324
## `http-proxy` events
325325

326-
Subscribe to [http-proxy events](https://github.com/nodejitsu/node-http-proxy#listening-for-proxy-events):
326+
Subscribe to [http-proxy events](https://github.com/nodejitsu/node-http-proxy#listening-for-proxy-events) with the `on` option:
327327

328-
- **option.onError**: function, subscribe to http-proxy's `error` event for custom error handling.
328+
```js
329+
createProxyMiddleware({
330+
target: 'http://www.example.org',
331+
on: {
332+
proxyReq: (proxyReq, req, res) => {
333+
/* handle proxyReq */
334+
},
335+
proxyRes: (proxyRes, req, res) => {
336+
/* handle proxyRes */
337+
},
338+
error: (err, req, res) => {
339+
/* handle error */
340+
},
341+
},
342+
});
343+
```
344+
345+
- **option.on.error**: function, subscribe to http-proxy's `error` event for custom error handling.
329346

330347
```javascript
331348
function onError(err, req, res, target) {
@@ -336,7 +353,7 @@ Subscribe to [http-proxy events](https://github.com/nodejitsu/node-http-proxy#li
336353
}
337354
```
338355

339-
- **option.onProxyRes**: function, subscribe to http-proxy's `proxyRes` event.
356+
- **option.on.proxyRes**: function, subscribe to http-proxy's `proxyRes` event.
340357

341358
```javascript
342359
function onProxyRes(proxyRes, req, res) {
@@ -345,7 +362,7 @@ Subscribe to [http-proxy events](https://github.com/nodejitsu/node-http-proxy#li
345362
}
346363
```
347364

348-
- **option.onProxyReq**: function, subscribe to http-proxy's `proxyReq` event.
365+
- **option.on.proxyReq**: function, subscribe to http-proxy's `proxyReq` event.
349366

350367
```javascript
351368
function onProxyReq(proxyReq, req, res) {
@@ -355,7 +372,7 @@ Subscribe to [http-proxy events](https://github.com/nodejitsu/node-http-proxy#li
355372
}
356373
```
357374

358-
- **option.onProxyReqWs**: function, subscribe to http-proxy's `proxyReqWs` event.
375+
- **option.on.proxyReqWs**: function, subscribe to http-proxy's `proxyReqWs` event.
359376

360377
```javascript
361378
function onProxyReqWs(proxyReq, req, socket, options, head) {
@@ -364,7 +381,7 @@ Subscribe to [http-proxy events](https://github.com/nodejitsu/node-http-proxy#li
364381
}
365382
```
366383

367-
- **option.onOpen**: function, subscribe to http-proxy's `open` event.
384+
- **option.on.open**: function, subscribe to http-proxy's `open` event.
368385

369386
```javascript
370387
function onOpen(proxySocket) {
@@ -373,7 +390,7 @@ Subscribe to [http-proxy events](https://github.com/nodejitsu/node-http-proxy#li
373390
}
374391
```
375392

376-
- **option.onClose**: function, subscribe to http-proxy's `close` event.
393+
- **option.on.close**: function, subscribe to http-proxy's `close` event.
377394

378395
```javascript
379396
function onClose(res, socket, head) {

examples/response-interceptor/index.js

+15-13
Original file line numberDiff line numberDiff line change
@@ -45,23 +45,25 @@ const jsonPlaceholderProxy = createProxyMiddleware({
4545
},
4646
changeOrigin: true, // for vhosted sites, changes host header to match to target's host
4747
selfHandleResponse: true, // manually call res.end(); IMPORTANT: res.end() is called internally by responseInterceptor()
48-
onProxyRes: responseInterceptor(async (buffer, proxyRes, req, res) => {
49-
// log original request and proxied request info
50-
const exchange = `[DEBUG] ${req.method} ${req.path} -> ${proxyRes.req.protocol}//${proxyRes.req.host}${proxyRes.req.path} [${proxyRes.statusCode}]`;
51-
console.log(exchange);
48+
on: {
49+
proxyRes: responseInterceptor(async (buffer, proxyRes, req, res) => {
50+
// log original request and proxied request info
51+
const exchange = `[DEBUG] ${req.method} ${req.path} -> ${proxyRes.req.protocol}//${proxyRes.req.host}${proxyRes.req.path} [${proxyRes.statusCode}]`;
52+
console.log(exchange);
5253

53-
// log original response
54-
// console.log(`[DEBUG] original response:\n${buffer.toString('utf8')}`);
54+
// log original response
55+
// console.log(`[DEBUG] original response:\n${buffer.toString('utf8')}`);
5556

56-
// set response content-type
57-
res.setHeader('content-type', 'application/json; charset=utf-8');
57+
// set response content-type
58+
res.setHeader('content-type', 'application/json; charset=utf-8');
5859

59-
// set response status code
60-
res.statusCode = 418;
60+
// set response status code
61+
res.statusCode = 418;
6162

62-
// return a complete different response
63-
return JSON.stringify(favoriteFoods);
64-
}),
63+
// return a complete different response
64+
return JSON.stringify(favoriteFoods);
65+
}),
66+
},
6567
logLevel: 'debug',
6668
});
6769

package.json

+2
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
"devDependencies": {
5656
"@commitlint/cli": "16.2.1",
5757
"@commitlint/config-conventional": "16.2.1",
58+
"@types/debug": "4.1.7",
5859
"@types/express": "4.17.13",
5960
"@types/is-glob": "4.0.2",
6061
"@types/jest": "27.4.0",
@@ -85,6 +86,7 @@
8586
},
8687
"dependencies": {
8788
"@types/http-proxy": "^1.17.8",
89+
"debug": "^4.3.4",
8890
"http-proxy": "^1.18.1",
8991
"is-glob": "^4.0.1",
9092
"is-plain-obj": "^3.0.0",

recipes/proxy-events.md

+21-9
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# Proxy Events
22

3-
Subscribe to [`http-proxy`](https://github.com/nodejitsu/node-http-proxy) [![GitHub stars](https://img.shields.io/github/stars/nodejitsu/node-http-proxy.svg?style=social&label=Star)](https://github.com/nodejitsu/node-http-proxy) events: `error`, `proxyReq`, `proxyReqWs`, `proxyRes`, `open`, `close`.
3+
Subscribe to [`http-proxy`](https://github.com/nodejitsu/node-http-proxy) [![GitHub stars](https://img.shields.io/github/stars/nodejitsu/node-http-proxy.svg?style=social&label=Star)](https://github.com/nodejitsu/node-http-proxy) events: `error`, `proxyReq`, `proxyReqWs`, `proxyRes`, `open`, `close`, `start`, `end`, `econnreset`.
44

5-
## onError
5+
## on.error
66

77
Subscribe to http-proxy's [error event](https://www.npmjs.com/package/http-proxy#listening-for-proxy-events).
88

@@ -14,12 +14,15 @@ const onError = function (err, req, res) {
1414
console.log('And we are reporting a custom error message.');
1515
};
1616

17-
const options = { target: 'http://localhost:3000', onError: onError };
17+
const options = {
18+
target: 'http://localhost:3000',
19+
on: { 'error', onError }
20+
};
1821

1922
const apiProxy = createProxyMiddleware(options);
2023
```
2124

22-
## onProxyReq
25+
## on.proxyReq
2326

2427
Subscribe to http-proxy's [proxyReq event](https://www.npmjs.com/package/http-proxy#listening-for-proxy-events).
2528

@@ -31,12 +34,15 @@ const onProxyReq = function (proxyReq, req, res) {
3134
proxyReq.setHeader('x-added', 'foobar');
3235
};
3336

34-
const options = { target: 'http://localhost:3000', onProxyReq: onProxyReq };
37+
const options = {
38+
target: 'http://localhost:3000',
39+
on: { 'proxyReq', onProxyReq }
40+
};
3541

3642
const apiProxy = createProxyMiddleware(options);
3743
```
3844

39-
## onProxyReqWs
45+
## on.proxyReqWs
4046

4147
Subscribe to http-proxy's [proxyReqWs event](https://www.npmjs.com/package/http-proxy#listening-for-proxy-events).
4248

@@ -48,12 +54,15 @@ const onProxyReqWs = function (proxyReq, req, socket, options, head) {
4854
proxyReq.setHeader('X-Special-Proxy-Header', 'foobar');
4955
};
5056

51-
const options = { target: 'http://localhost:3000', onProxyReqWs: onProxyReqWs };
57+
const options = {
58+
target: 'http://localhost:3000',
59+
on: { 'proxyReqWs', onProxyReqWs }
60+
};
5261

5362
const apiProxy = createProxyMiddleware(options);
5463
```
5564

56-
## onProxyRes
65+
## on.proxyRes
5766

5867
Subscribe to http-proxy's [proxyRes event](https://www.npmjs.com/package/http-proxy#listening-for-proxy-events).
5968

@@ -68,7 +77,10 @@ const onProxyRes = function (proxyRes, req, res) {
6877
delete proxyRes.headers['x-removed'];
6978
};
7079

71-
const options = { target: 'http://localhost:3000', onProxyRes: onProxyRes };
80+
const options = {
81+
target: 'http://localhost:3000',
82+
on: { 'proxyRes', onProxyRes }
83+
};
7284

7385
const apiProxy = createProxyMiddleware(options);
7486
```

src/_handlers.ts

-87
This file was deleted.

src/debug.ts

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import * as createDebug from 'debug';
2+
3+
/**
4+
* Debug instance with the given namespace: hpm
5+
*/
6+
export const debug = createDebug('hpm');

src/http-proxy-middleware.ts

+14-24
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
import type * as https from 'https';
2-
import type * as express from 'express';
3-
import type { Request, RequestHandler, Response, Options, Filter } from './types';
2+
import type { Request, RequestHandler, Options, Filter } from './types';
43
import * as httpProxy from 'http-proxy';
54
import { verifyConfig } from './configuration';
65
import { matchPathFilter } from './path-filter';
7-
import * as handlers from './_handlers';
86
import { getArrow, getInstance } from './logger';
97
import * as PathRewriter from './path-rewriter';
108
import * as Router from './router';
9+
import {
10+
debugProxyErrorsPlugin,
11+
createLoggerPlugin,
12+
errorResponsePlugin,
13+
proxyEventsPlugin,
14+
} from './plugins/default';
1115

1216
export class HttpProxyMiddleware {
1317
private logger = getInstance();
@@ -29,12 +33,6 @@ export class HttpProxyMiddleware {
2933

3034
this.pathRewriter = PathRewriter.createPathRewriter(this.proxyOptions.pathRewrite); // returns undefined when "pathRewrite" is not provided
3135

32-
// attach handler to http-proxy events
33-
handlers.init(this.proxy, this.proxyOptions);
34-
35-
// log errors for debug purpose
36-
this.proxy.on('error', this.logError);
37-
3836
// https://github.com/chimurai/http-proxy-middleware/issues/19
3937
// expose function to upgrade externally
4038
this.middleware.upgrade = (req, socket, head) => {
@@ -82,8 +80,14 @@ export class HttpProxyMiddleware {
8280
};
8381

8482
private registerPlugins(proxy: httpProxy, options: Options) {
83+
const defaultPlugins = [
84+
debugProxyErrorsPlugin,
85+
proxyEventsPlugin,
86+
createLoggerPlugin(),
87+
errorResponsePlugin,
88+
];
8589
const plugins = options.plugins ?? [];
86-
plugins.forEach((plugin) => plugin(proxy, options));
90+
[...defaultPlugins, ...plugins].forEach((plugin) => plugin(proxy, options));
8791
}
8892

8993
private catchUpgradeRequest = (server: https.Server) => {
@@ -175,18 +179,4 @@ export class HttpProxyMiddleware {
175179
}
176180
}
177181
};
178-
179-
private logError = (err, req: Request, res: Response, target?) => {
180-
const hostname =
181-
req.headers?.host ||
182-
(req as Request<express.Request>).hostname ||
183-
(req as Request<express.Request>).host; // (websocket) || (node0.10 || node 4/5)
184-
const requestHref = `${hostname}${req.url}`;
185-
const targetHref = `${target?.href}`; // target is undefined when websocket errors
186-
187-
const errorMessage = '[HPM] Error occurred while proxying request %s to %s [%s] (%s)';
188-
const errReference = 'https://nodejs.org/api/errors.html#errors_common_system_errors'; // link to Node Common Systems Errors page
189-
190-
this.logger.error(errorMessage, requestHref, targetHref, err.code || err, errReference);
191-
};
192182
}

0 commit comments

Comments
 (0)