diff --git a/package.json b/package.json index 779939d4..8fecb034 100644 --- a/package.json +++ b/package.json @@ -90,14 +90,6 @@ "is-plain-obj": "^3.0.0", "micromatch": "^4.0.2" }, - "peerDependencies": { - "@types/express": "^4.17.13" - }, - "peerDependenciesMeta": { - "@types/express": { - "optional": true - } - }, "engines": { "node": ">=12.0.0" }, diff --git a/src/_handlers.ts b/src/_handlers.ts index 6cdefd79..4a8b6be2 100644 --- a/src/_handlers.ts +++ b/src/_handlers.ts @@ -1,5 +1,4 @@ -import type * as express from 'express'; -import type { Options } from './types'; +import type { Request, Response, Options } from './types'; import type * as httpProxy from 'http-proxy'; import { getInstance } from './logger'; const logger = getInstance(); @@ -53,7 +52,7 @@ export function getHandlers(options: Options) { return handlers; } -function defaultErrorHandler(err, req: express.Request, res: express.Response) { +function defaultErrorHandler(err, req: Request, res: Response) { // Re-throw error. Not recoverable since req & res are empty. if (!req && !res) { throw err; // "Error: Must provide a proper URL as target" diff --git a/src/handlers/fix-request-body.ts b/src/handlers/fix-request-body.ts index 1855f569..24108511 100644 --- a/src/handlers/fix-request-body.ts +++ b/src/handlers/fix-request-body.ts @@ -5,8 +5,8 @@ import * as querystring from 'querystring'; /** * Fix proxied body if bodyParser is involved. */ -export function fixRequestBody(proxyReq: http.ClientRequest, req: http.IncomingMessage): void { - const requestBody = (req as Request).body; +export function fixRequestBody(proxyReq: http.ClientRequest, req: Request): void { + const requestBody = req.body; if (!requestBody) { return; diff --git a/src/http-proxy-middleware.ts b/src/http-proxy-middleware.ts index b93ae92f..5928bd5b 100644 --- a/src/http-proxy-middleware.ts +++ b/src/http-proxy-middleware.ts @@ -1,6 +1,5 @@ import type * as https from 'https'; -import type * as express from 'express'; -import type { Filter, Request, RequestHandler, Response, Options } from './types'; +import type { Filter, Request, RequestMiddleware, Response, Options } from './types'; import * as httpProxy from 'http-proxy'; import { createConfig, Config } from './config-factory'; import * as contextMatcher from './context-matcher'; @@ -8,6 +7,7 @@ import * as handlers from './_handlers'; import { getArrow, getInstance } from './logger'; import * as PathRewriter from './path-rewriter'; import * as Router from './router'; + export class HttpProxyMiddleware { private logger = getInstance(); private config: Config; @@ -35,7 +35,7 @@ export class HttpProxyMiddleware { // https://github.com/chimurai/http-proxy-middleware/issues/19 // expose function to upgrade externally - (this.middleware as any).upgrade = (req, socket, head) => { + this.middleware.upgrade = (req, socket, head) => { if (!this.wsInternalSubscribed) { this.handleUpgrade(req, socket, head); } @@ -43,11 +43,7 @@ export class HttpProxyMiddleware { } // https://github.com/Microsoft/TypeScript/wiki/'this'-in-TypeScript#red-flags-for-this - public middleware: RequestHandler = async ( - req: Request, - res: Response, - next: express.NextFunction - ) => { + public middleware: RequestMiddleware = async (req, res, next) => { if (this.shouldProxy(this.config.context, req)) { try { const activeProxyOptions = await this.prepareProxyRequest(req); @@ -58,7 +54,6 @@ export class HttpProxyMiddleware { } else { next(); } - /** * Get the server object to subscribe to server events; * 'upgrade' for websocket and 'close' for graceful shutdown diff --git a/src/index.ts b/src/index.ts index 79a95325..59ccf6d3 100644 --- a/src/index.ts +++ b/src/index.ts @@ -8,4 +8,4 @@ export function createProxyMiddleware(context: Filter | Options, options?: Optio export * from './handlers'; -export { Filter, Options, RequestHandler } from './types'; +export { Filter, Options, RequestMiddleware } from './types'; diff --git a/src/types.ts b/src/types.ts index 55628aab..a2cfbc02 100644 --- a/src/types.ts +++ b/src/types.ts @@ -4,20 +4,40 @@ */ /* eslint-disable @typescript-eslint/no-empty-interface */ - -import type * as express from 'express'; import type * as http from 'http'; import type * as httpProxy from 'http-proxy'; import type * as net from 'net'; import type * as url from 'url'; -export interface Request extends express.Request {} -export interface Response extends express.Response {} +export type Request = http.IncomingMessage; +export type Response = http.ServerResponse; -export interface RequestHandler extends express.RequestHandler { - upgrade?: (req: Request, socket: net.Socket, head: any) => void; +/** + * http-proxy-middleware supports framework specific values. The following + * values are primarily decorated onto IncomingMessage by express, but are + * not required for use. + */ +declare module 'http' { + interface IncomingMessage { + originalUrl?: string; + hostname?: string; + host?: string; + body?: Record; + } } +export type Next = (...args: unknown[]) => unknown; + +type RequestMiddlewareFunction = ( + req: http.IncomingMessage, + res: http.ServerResponse, + next: Next +) => unknown | Promise; + +export type RequestMiddleware = RequestMiddlewareFunction & { + upgrade?: (req: Request, socket: net.Socket, head: any) => void; +}; + export type Filter = string | string[] | ((pathname: string, req: Request) => boolean); export interface Options extends httpProxy.ServerOptions { diff --git a/test/e2e/express-router.spec.ts b/test/e2e/servers/express-router.spec.ts similarity index 93% rename from test/e2e/express-router.spec.ts rename to test/e2e/servers/express-router.spec.ts index 611247be..39930340 100644 --- a/test/e2e/express-router.spec.ts +++ b/test/e2e/servers/express-router.spec.ts @@ -1,7 +1,7 @@ import * as express from 'express'; import * as request from 'supertest'; -import { createProxyMiddleware } from './test-kit'; -import { Options } from '../../src/index'; +import { createProxyMiddleware } from '../test-kit'; +import { Options } from '../../../src/index'; describe('Usage in Express', () => { let app: express.Express; diff --git a/test/e2e/servers/http.spec.ts b/test/e2e/servers/http.spec.ts new file mode 100644 index 00000000..f46ae4e6 --- /dev/null +++ b/test/e2e/servers/http.spec.ts @@ -0,0 +1,35 @@ +import * as http from 'http'; +import { createProxyMiddleware } from '../test-kit'; +import { Options } from '../../../src/index'; +import * as request from 'supertest'; +import * as getPort from 'get-port'; + +describe('http integration', () => { + it('should work with raw node http RequestHandler', async () => { + await new Promise(async (resolve, reject) => { + const port = await getPort(); + const server = http + .createServer((req, res) => { + const proxyConfig: Options = { + changeOrigin: true, + logLevel: 'silent', + target: 'http://jsonplaceholder.typicode.com', + }; + const handler = createProxyMiddleware(proxyConfig); + return handler(req, res, resolve); + }) + .listen(port); + request(server) + .get('/') + .expect(200) + .end((err, res) => { + if (err) { + reject(err); + } else { + expect(res.ok).toBe(true); + resolve(res); + } + }); + }); + }); +}); diff --git a/test/e2e/websocket.spec.ts b/test/e2e/websocket.spec.ts index ad946d4a..38b24bae 100644 --- a/test/e2e/websocket.spec.ts +++ b/test/e2e/websocket.spec.ts @@ -3,7 +3,7 @@ import * as WebSocket from 'ws'; import { Server as WebSocketServer } from 'ws'; import * as getPort from 'get-port'; import { createProxyMiddleware, createApp } from './test-kit'; -import type { RequestHandler } from '../../src/types'; +import type { RequestMiddleware } from '../../src/types'; /******************************************************************** * - Not possible to use `supertest` to test WebSockets @@ -14,7 +14,7 @@ describe('E2E WebSocket proxy', () => { let proxyServer: http.Server; let ws: WebSocket; let wss: WebSocketServer; - let proxyMiddleware: RequestHandler; + let proxyMiddleware: RequestMiddleware; let WS_SERVER_PORT: number; let SERVER_PORT: number; diff --git a/test/unit/fix-request-body.spec.ts b/test/unit/fix-request-body.spec.ts index 96677502..e9a37717 100644 --- a/test/unit/fix-request-body.spec.ts +++ b/test/unit/fix-request-body.spec.ts @@ -44,7 +44,7 @@ describe('fixRequestBody', () => { jest.spyOn(proxyRequest, 'setHeader'); jest.spyOn(proxyRequest, 'write'); - fixRequestBody(proxyRequest, { body: { someField: 'some value' } } as Request); + fixRequestBody(proxyRequest, { body: { someField: 'some value' } } as unknown as Request); const expectedBody = JSON.stringify({ someField: 'some value' }); expect(proxyRequest.setHeader).toHaveBeenCalledWith('Content-Length', expectedBody.length); @@ -58,7 +58,7 @@ describe('fixRequestBody', () => { jest.spyOn(proxyRequest, 'setHeader'); jest.spyOn(proxyRequest, 'write'); - fixRequestBody(proxyRequest, { body: { someField: 'some value' } } as Request); + fixRequestBody(proxyRequest, { body: { someField: 'some value' } } as unknown as Request); const expectedBody = querystring.stringify({ someField: 'some value' }); expect(proxyRequest.setHeader).toHaveBeenCalledWith('Content-Length', expectedBody.length);