Skip to content

Commit

Permalink
feat(types): support contextual typing from server
Browse files Browse the repository at this point in the history
  • Loading branch information
chimurai committed Feb 25, 2023
1 parent 3fd88a1 commit 6c7d2c4
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 11 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -2,6 +2,7 @@

## next

- feat(typescript): type improvements ([#882](https://github.com/chimurai/http-proxy-middleware/pull/882))
- chore(deps): update micromatch to 4.0.5
- chore(package): bump devDependencies
- feat(legacyCreateProxyMiddleware): show migration tips ([#756](https://github.com/chimurai/http-proxy-middleware/pull/756))
Expand Down
2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -83,7 +83,7 @@
"ws": "8.10.0"
},
"dependencies": {
"@types/http-proxy": "^1.17.9",
"@types/http-proxy": "^1.17.10",
"debug": "^4.3.4",
"http-proxy": "^1.18.1",
"is-glob": "^4.0.1",
Expand Down
4 changes: 2 additions & 2 deletions src/http-proxy-middleware.ts
Expand Up @@ -14,7 +14,7 @@ export class HttpProxyMiddleware<TReq, TRes> {
private wsInternalSubscribed = false;
private serverOnCloseSubscribed = false;
private proxyOptions: Options<TReq, TRes>;
private proxy: httpProxy;
private proxy: httpProxy<TReq, TRes>;
private pathRewriter;

constructor(options: Options<TReq, TRes>) {
Expand Down Expand Up @@ -75,7 +75,7 @@ export class HttpProxyMiddleware<TReq, TRes> {
}
};

private registerPlugins(proxy: httpProxy, options: Options<TReq, TRes>) {
private registerPlugins(proxy: httpProxy<TReq, TRes>, options: Options<TReq, TRes>) {
const plugins = getPlugins<TReq, TRes>(options);
plugins.forEach((plugin) => {
debug(`register plugin: "${getFunctionName(plugin)}"`);
Expand Down
2 changes: 1 addition & 1 deletion src/types.ts
Expand Up @@ -26,7 +26,7 @@ export type Filter<TReq = http.IncomingMessage> =
| ((pathname: string, req: TReq) => boolean);

export interface Plugin<TReq = http.IncomingMessage, TRes = http.ServerResponse> {
(proxyServer: httpProxy, options: Options<TReq, TRes>): void;
(proxyServer: httpProxy<TReq, TRes>, options: Options<TReq, TRes>): void;
}

export interface OnProxyEvent<TReq = http.IncomingMessage, TRes = http.ServerResponse> {
Expand Down
90 changes: 87 additions & 3 deletions test/types.spec.ts
Expand Up @@ -193,6 +193,57 @@ describe('http-proxy-middleware TypeScript Types', () => {
expect(app).toBeDefined();
});

// FIXME: contextual types should work with express path middleware
// it('should get contextual types from express server', () => {
// const app = express();
// app.use(
// '/',
// middleware({
// router: (req) => req.params,
// pathFilter: (pathname, req) => !!req.params,
// on: {
// error(error, req, res, target) {
// req.params;

// // https://www.typescriptlang.org/docs/handbook/2/narrowing.html
// if (res instanceof http.ServerResponse) {
// res.status(200).send('OK');
// }
// },
// proxyReq(proxyReq, req, res, options) {
// req.params;
// res.status(200).send('OK');
// },
// proxyReqWs(proxyReq, req, socket, options, head) {
// req.params;
// },
// proxyRes(proxyRes, req, res) {
// req.params;
// res.status(200).send('OK');
// },
// close(proxyRes, proxySocket, proxyHead) {
// proxyRes.params;
// },
// start(req, res, target) {
// req.params;
// res.status(200).send('OK');
// },
// end(req, res, proxyRes) {
// req.params;
// res.status(200).send('OK');
// proxyRes.params;
// },
// econnreset(error, req, res, target) {
// req.params;
// res.status(200).send('OK');
// },
// },
// })
// );

// expect(app).toBeDefined();
// });

it('should work with explicit generic custom req & res types', () => {
interface MyRequest extends http.IncomingMessage {
myRequestParams: { [key: string]: string };
Expand Down Expand Up @@ -260,6 +311,9 @@ describe('http-proxy-middleware TypeScript Types', () => {
const proxy: RequestHandler<MyRequest, MyResponse> = middleware({
target: 'http://www.example.org',
on: {
error: (err: Error & { code?: string }, req, res) => {
err.code;
},
proxyRes: responseInterceptor(async (buffer, proxyRes, req, res) => {
req.myRequestParams;
res.myResponseParams;
Expand All @@ -282,17 +336,47 @@ describe('http-proxy-middleware TypeScript Types', () => {
expect(proxy).toBeDefined();
});

it('should work with express.Request with fixRequestBody in plugins', () => {
const proxy: RequestHandler<express.Request> = middleware({
it('should work with generic types in plugins', () => {
const proxy: RequestHandler<express.Request, express.Response> = middleware({
target: 'http://www.example.org',
plugins: [
(proxyServer, options) => {
proxyServer.on('proxyReq', fixRequestBody);
proxyServer.on('proxyReq', (proxyReq, req, res, options) => {
req.params;
res.status(200).send('OK');
});
},
],
});

expect(proxy).toBeDefined();
});

it('should work with contextual Express types with shipped plugins', () => {
const app = express();
app.use(
middleware({
target: 'http://www.example.org',
plugins: [
(proxyServer, options) => {
// fixRequestBody
proxyServer.on('proxyReq', fixRequestBody);

// responseInterceptor
proxyServer.on(
'proxyRes',
responseInterceptor(async (buffer, proxyRes, req, res) => {
req.params;
res.status(200).send('OK');
return buffer;
})
);
},
],
})
);

expect(app).toBeDefined();
});
});
});
8 changes: 4 additions & 4 deletions yarn.lock
Expand Up @@ -984,10 +984,10 @@
dependencies:
"@types/node" "*"

"@types/http-proxy@^1.17.9":
version "1.17.9"
resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.9.tgz#7f0e7931343761efde1e2bf48c40f02f3f75705a"
integrity sha512-QsbSjA/fSk7xB+UXlCT3wHBy5ai9wOcNDWwZAtud+jXhwOM3l+EYZh8Lng4+/6n8uar0J7xILzqftJdJ/Wdfkw==
"@types/http-proxy@^1.17.10":
version "1.17.10"
resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.10.tgz#e576c8e4a0cc5c6a138819025a88e167ebb38d6c"
integrity sha512-Qs5aULi+zV1bwKAg5z1PWnDXWmsn+LxIvUGv6E2+OOMYhclZMO+OXd9pYVf2gLykf2I7IV2u7oTHwChPNsvJ7g==
dependencies:
"@types/node" "*"

Expand Down

0 comments on commit 6c7d2c4

Please sign in to comment.