Skip to content

Commit f01e972

Browse files
committed
refactor: use node http base types [BREAKING CHANGE]
1 parent 0b30c5d commit f01e972

14 files changed

+116
-46
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
[![dependency Status](https://snyk.io/test/npm/http-proxy-middleware/badge.svg?style=flat-square)](https://snyk.io/test/npm/http-proxy-middleware)
66
[![npm](https://img.shields.io/npm/v/http-proxy-middleware?color=%23CC3534&style=flat-square)](https://www.npmjs.com/package/http-proxy-middleware)
77

8-
Node.js proxying made simple. Configure proxy middleware with ease for [connect](https://github.com/senchalabs/connect), [express](https://github.com/strongloop/express), [browser-sync](https://github.com/BrowserSync/browser-sync) and [many more](#compatible-servers).
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).
99

1010
Powered by the popular Nodejitsu [`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)
1111

@@ -534,6 +534,7 @@ View the [recipes](https://github.com/chimurai/http-proxy-middleware/tree/master
534534

535535
- [connect](https://www.npmjs.com/package/connect)
536536
- [express](https://www.npmjs.com/package/express)
537+
- [next.js](https://www.npmjs.com/package/next)
537538
- [fastify](https://www.npmjs.com/package/fastify)
538539
- [browser-sync](https://www.npmjs.com/package/browser-sync)
539540
- [lite-server](https://www.npmjs.com/package/lite-server)

cspell.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
"middlewares",
2727
"millis",
2828
"mockttp",
29+
"nextjs",
2930
"Nodejitsu",
3031
"ntlm",
3132
"proxied",

jest.config.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */
12
module.exports = {
23
preset: 'ts-jest',
34
testEnvironment: 'node',
45
coverageReporters: ['text', 'lcov'],
56
collectCoverageFrom: ['src/**/*.*'],
7+
setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
68
};

jest.setup.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/**
2+
* Uncomment the following lines for less noise in test output
3+
*/
4+
5+
// console.info = jest.fn();
6+
// console.log = jest.fn();
7+
// console.error = jest.fn();

recipes/servers.md

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,9 @@ Overview of `http-proxy-middleware` implementation in different servers.
44

55
Missing a server? Feel free to extend this list of examples.
66

7-
<!-- TOC depthfrom:2 insertanchor:false -->
8-
97
- [Express](#express)
108
- [Connect](#connect)
9+
- [Next.js](#nextjs)
1110
- [Browser-Sync](#browser-sync)
1211
- [fastify](#fastify)
1312
- [Polka](#polka)
@@ -17,8 +16,6 @@ Missing a server? Feel free to extend this list of examples.
1716
- [grunt-browser-sync](#grunt-browser-sync)
1817
- [gulp-webserver](#gulp-webserver)
1918

20-
<!-- /TOC -->
21-
2219
## Express
2320

2421
https://github.com/expressjs/express
@@ -62,6 +59,38 @@ app.use(apiProxy);
6259
http.createServer(app).listen(3000);
6360
```
6461

62+
## Next.js
63+
64+
https://github.com/vercel/next.js
65+
[![GitHub stars](https://img.shields.io/github/stars/vercel/next.js.svg?style=social&label=Star)](https://github.com/vercel/next.js)
66+
![next.js downloads](https://img.shields.io/npm/dm/next)
67+
68+
Next project: `/pages/api/users.ts`
69+
70+
```typescript
71+
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
72+
import type { NextApiRequest, NextApiResponse } from 'next';
73+
import { createProxyMiddleware } from 'http-proxy-middleware';
74+
75+
const proxyMiddleware = createProxyMiddleware({
76+
target: 'http://jsonplaceholder.typicode.com',
77+
changeOrigin: true,
78+
pathRewrite: {
79+
'^/api/users': '/users',
80+
},
81+
});
82+
83+
export default function handler(req: NextApiRequest, res: NextApiResponse) {
84+
proxyMiddleware(req, res, (result: unknown) => {
85+
if (result instanceof Error) {
86+
throw result;
87+
}
88+
});
89+
}
90+
91+
// curl http://localhost:3000/api/users
92+
```
93+
6594
## Browser-Sync
6695

6796
https://github.com/BrowserSync/browser-sync

src/_handlers.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
import type * as express from 'express';
2-
import type { Options } from './types';
1+
import type { Options, Request, Response } from './types';
32
import type * as httpProxy from 'http-proxy';
43
import { getInstance } from './logger';
54
const logger = getInstance();
@@ -53,7 +52,7 @@ export function getHandlers(options: Options) {
5352
return handlers;
5453
}
5554

56-
function defaultErrorHandler(err, req: express.Request, res: express.Response) {
55+
function defaultErrorHandler(err, req: Request, res: Response) {
5756
// Re-throw error. Not recoverable since req & res are empty.
5857
if (!req && !res) {
5958
throw err; // "Error: Must provide a proper URL as target"

src/handlers/fix-request-body.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import type * as http from 'http';
2+
import type * as express from 'express';
23
import type { Request } from '../types';
34
import * as querystring from 'querystring';
45

56
/**
67
* Fix proxied body if bodyParser is involved.
78
*/
8-
export function fixRequestBody(proxyReq: http.ClientRequest, req: http.IncomingMessage): void {
9-
const requestBody = (req as Request).body;
9+
export function fixRequestBody(proxyReq: http.ClientRequest, req: Request): void {
10+
const requestBody = (req as Request<express.Request>).body;
1011

1112
if (!requestBody) {
1213
return;

src/http-proxy-middleware.ts

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -35,28 +35,24 @@ export class HttpProxyMiddleware {
3535

3636
// https://github.com/chimurai/http-proxy-middleware/issues/19
3737
// expose function to upgrade externally
38-
(this.middleware as any).upgrade = (req, socket, head) => {
38+
this.middleware.upgrade = (req, socket, head) => {
3939
if (!this.wsInternalSubscribed) {
4040
this.handleUpgrade(req, socket, head);
4141
}
4242
};
4343
}
4444

4545
// https://github.com/Microsoft/TypeScript/wiki/'this'-in-TypeScript#red-flags-for-this
46-
public middleware: RequestHandler = async (
47-
req: Request,
48-
res: Response,
49-
next: express.NextFunction
50-
) => {
46+
public middleware: RequestHandler = async (req, res, next?) => {
5147
if (this.shouldProxy(this.proxyOptions.pathFilter, req)) {
5248
try {
5349
const activeProxyOptions = await this.prepareProxyRequest(req);
5450
this.proxy.web(req, res, activeProxyOptions);
5551
} catch (err) {
56-
next(err);
52+
next && next(err);
5753
}
5854
} else {
59-
next();
55+
next && next();
6056
}
6157

6258
/**
@@ -104,7 +100,7 @@ export class HttpProxyMiddleware {
104100
* Determine whether request should be proxied.
105101
*/
106102
private shouldProxy = (pathFilter: Filter, req: Request): boolean => {
107-
const path = req.originalUrl || req.url;
103+
const path = (req as Request<express.Request>).originalUrl || req.url;
108104
return matchPathFilter(pathFilter, path, req);
109105
};
110106

@@ -119,7 +115,7 @@ export class HttpProxyMiddleware {
119115
private prepareProxyRequest = async (req: Request) => {
120116
// https://github.com/chimurai/http-proxy-middleware/issues/17
121117
// https://github.com/chimurai/http-proxy-middleware/issues/94
122-
req.url = req.originalUrl || req.url;
118+
req.url = (req as Request<express.Request>).originalUrl || req.url;
123119

124120
// store uri before it gets rewritten for logging
125121
const originalPath = req.url;
@@ -179,7 +175,10 @@ export class HttpProxyMiddleware {
179175
};
180176

181177
private logError = (err, req: Request, res: Response, target?) => {
182-
const hostname = req.headers?.host || req.hostname || req.host; // (websocket) || (node0.10 || node 4/5)
178+
const hostname =
179+
req.headers?.host ||
180+
(req as Request<express.Request>).hostname ||
181+
(req as Request<express.Request>).host; // (websocket) || (node0.10 || node 4/5)
183182
const requestHref = `${hostname}${req.url}`;
184183
const targetHref = `${target?.href}`; // target is undefined when websocket errors
185184

src/index.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { HttpProxyMiddleware } from './http-proxy-middleware';
2-
import { Options } from './types';
2+
import type { Options, RequestHandler } from './types';
33

4-
export function createProxyMiddleware(options: Options) {
4+
export function createProxyMiddleware(options: Options): RequestHandler {
55
const { middleware } = new HttpProxyMiddleware(options);
66
return middleware;
77
}
@@ -15,4 +15,4 @@ export function createProxyMiddleware(options: Options) {
1515

1616
export * from './handlers';
1717

18-
export { Filter, Options, RequestHandler } from './types';
18+
export type { Filter, Options, RequestHandler } from './types';

src/types.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,17 @@
55

66
/* eslint-disable @typescript-eslint/no-empty-interface */
77

8-
import type * as express from 'express';
98
import type * as http from 'http';
109
import type * as httpProxy from 'http-proxy';
1110
import type * as net from 'net';
1211
import type * as url from 'url';
1312

14-
export interface Request extends express.Request {}
15-
export interface Response extends express.Response {}
13+
export type Request<T = http.IncomingMessage> = T;
14+
export type Response<T = http.ServerResponse> = T;
15+
export type NextFunction<T = (err?: any) => void> = T;
1616

17-
export interface RequestHandler extends express.RequestHandler {
17+
export interface RequestHandler {
18+
(req: Request, res: Response, next?: NextFunction): void | Promise<void>;
1819
upgrade?: (req: Request, socket: net.Socket, head: any) => void;
1920
}
2021

0 commit comments

Comments
 (0)