Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(typescript): types support #369

Merged
merged 1 commit into from Feb 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -3,6 +3,7 @@
## next

- feat: async router ([#379](https://github.com/chimurai/http-proxy-middleware/issues/335)) ([LiranBri](https://github.com/LiranBri))
- feat(typescript): types support ([#369](https://github.com/chimurai/http-proxy-middleware/pull/369))

## [v0.20.0](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.20.0)

Expand Down
5 changes: 3 additions & 2 deletions package.json
@@ -1,8 +1,9 @@
{
"name": "http-proxy-middleware",
"version": "0.21.0-beta.1",
"version": "0.21.0-beta.2",
"description": "The one-liner node.js proxy middleware for connect, express and browser-sync",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"files": [
"dist"
],
Expand Down Expand Up @@ -51,7 +52,6 @@
"@commitlint/cli": "^8.0.0",
"@commitlint/config-conventional": "^8.0.0",
"@types/express": "^4.17.0",
"@types/http-proxy": "^1.17.0",
"@types/is-glob": "^4.0.0",
"@types/jest": "^24.0.15",
"@types/lodash": "^4.14.136",
Expand All @@ -72,6 +72,7 @@
"ws": "^7.1.0"
},
"dependencies": {
"@types/http-proxy": "^1.17.2",
"http-proxy": "^1.17.0",
"is-glob": "^4.0.1",
"lodash": "^4.17.14",
Expand Down
13 changes: 7 additions & 6 deletions src/config-factory.ts
@@ -1,15 +1,16 @@
import * as _ from 'lodash';
import * as url from 'url';
import _ from 'lodash';
import url from 'url';
import { ERRORS } from './errors';
import { getInstance } from './logger';
import { Filter, Options } from './types';

const logger = getInstance();

export function createConfig(context, opts?) {
// structure of config object to be returned
const config = {
context: undefined,
options: {} as any
options: {} as Options
};

// app.use('/api', proxy({target:'http://localhost:9000'}));
Expand Down Expand Up @@ -55,7 +56,7 @@ export function createConfig(context, opts?) {
* @param {String} context [description]
* @return {Boolean} [description]
*/
function isStringShortHand(context) {
function isStringShortHand(context: Filter) {
if (_.isString(context)) {
return !!url.parse(context).host;
}
Expand All @@ -72,11 +73,11 @@ function isStringShortHand(context) {
* @param {*} opts [description]
* @return {Boolean} [description]
*/
function isContextless(context, opts) {
function isContextless(context: Filter, opts: Options) {
return _.isPlainObject(context) && _.isEmpty(opts);
}

function configureLogger(options) {
function configureLogger(options: Options) {
if (options.logLevel) {
logger.setLevel(options.logLevel);
}
Expand Down
8 changes: 4 additions & 4 deletions src/context-matcher.ts
@@ -1,7 +1,7 @@
import * as isGlob from 'is-glob';
import * as _ from 'lodash';
import * as micromatch from 'micromatch';
import * as url from 'url';
import isGlob from 'is-glob';
import _ from 'lodash';
import micromatch from 'micromatch';
import url from 'url';
import { ERRORS } from './errors';

export function match(context, uri, req) {
Expand Down
2 changes: 1 addition & 1 deletion src/handlers.ts
@@ -1,4 +1,4 @@
import * as _ from 'lodash';
import _ from 'lodash';
import { getInstance } from './logger';
const logger = getInstance();

Expand Down
35 changes: 21 additions & 14 deletions src/http-proxy-middleware.ts
@@ -1,21 +1,23 @@
import * as httpProxy from 'http-proxy';
import * as _ from 'lodash';
import express from 'express';
import httpProxy from 'http-proxy';
import _ from 'lodash';
import { createConfig } from './config-factory';
import * as contextMatcher from './context-matcher';
import * as handlers from './handlers';
import { getArrow, getInstance } from './logger';
import * as PathRewriter from './path-rewriter';
import * as Router from './router';
import { Filter, IRequest, IRequestHandler, IResponse, Options } from './types';

export class HttpProxyMiddleware {
private logger = getInstance();
private config;
private wsInternalSubscribed = false;
private proxyOptions;
private proxy;
private proxyOptions: Options;
private proxy: httpProxy;
private pathRewriter;

constructor(context, opts) {
constructor(context: Filter | Options, opts?: Options) {
this.config = createConfig(context, opts);
this.proxyOptions = this.config.options;

Expand Down Expand Up @@ -45,7 +47,11 @@ export class HttpProxyMiddleware {
}

// https://github.com/Microsoft/TypeScript/wiki/'this'-in-TypeScript#red-flags-for-this
public middleware = async (req, res, next) => {
public middleware: IRequestHandler = async (
req: IRequest,
res: IResponse,
next: express.NextFunction
) => {
if (this.shouldProxy(this.config.context, req)) {
const activeProxyOptions = await this.prepareProxyRequest(req);
this.proxy.web(req, res, activeProxyOptions);
Expand All @@ -55,7 +61,7 @@ export class HttpProxyMiddleware {

if (this.proxyOptions.ws === true) {
// use initial request to access the server object to subscribe to http upgrade event
this.catchUpgradeRequest(req.connection.server);
this.catchUpgradeRequest((req.connection as any).server);
}
};

Expand All @@ -68,7 +74,7 @@ export class HttpProxyMiddleware {
}
};

private handleUpgrade = async (req, socket, head) => {
private handleUpgrade = async (req: IRequest, socket, head) => {
if (this.shouldProxy(this.config.context, req)) {
const activeProxyOptions = await this.prepareProxyRequest(req);
this.proxy.ws(req, socket, head, activeProxyOptions);
Expand All @@ -84,7 +90,7 @@ export class HttpProxyMiddleware {
* @param {Object} req [description]
* @return {Boolean}
*/
private shouldProxy = (context, req) => {
private shouldProxy = (context, req: IRequest) => {
const path = req.originalUrl || req.url;
return contextMatcher.match(context, path, req);
};
Expand All @@ -97,7 +103,7 @@ export class HttpProxyMiddleware {
* @param {Object} req
* @return {Object} proxy options
*/
private prepareProxyRequest = async req => {
private prepareProxyRequest = async (req: IRequest) => {
// https://github.com/chimurai/http-proxy-middleware/issues/17
// https://github.com/chimurai/http-proxy-middleware/issues/94
req.url = req.originalUrl || req.url;
Expand Down Expand Up @@ -133,7 +139,7 @@ export class HttpProxyMiddleware {
};

// Modify option.target when router present.
private applyRouter = async (req, options) => {
private applyRouter = async (req: IRequest, options) => {
let newTarget;

if (options.router) {
Expand All @@ -151,7 +157,7 @@ export class HttpProxyMiddleware {
};

// rewrite path
private applyPathRewrite = (req, pathRewriter) => {
private applyPathRewrite = (req: IRequest, pathRewriter) => {
if (pathRewriter) {
const path = pathRewriter(req.url, req);

Expand All @@ -166,10 +172,11 @@ export class HttpProxyMiddleware {
}
};

private logError = (err, req, res) => {
private logError = (err, req: IRequest, res: IResponse) => {
const hostname =
(req.headers && req.headers.host) || (req.hostname || req.host); // (websocket) || (node0.10 || node 4/5)
const target = this.proxyOptions.target.host || this.proxyOptions.target;
const target =
(this.proxyOptions.target as any).host || this.proxyOptions.target;
const errorMessage =
'[HPM] Error occurred while trying to proxy request %s from %s to %s (%s) (%s)';
const errReference =
Expand Down
7 changes: 4 additions & 3 deletions src/index.ts
@@ -1,8 +1,9 @@
import { HttpProxyMiddleware } from './http-proxy-middleware';
import { Filter, Options } from './types';

function proxy(context, opts) {
const { middleware } = new HttpProxyMiddleware(context, opts);
function middleware(context: Filter | Options, options?: Options) {
const { middleware } = new HttpProxyMiddleware(context, options);
return middleware;
}

export = proxy;
export = middleware;
4 changes: 2 additions & 2 deletions src/logger.ts
@@ -1,5 +1,5 @@
import * as _ from 'lodash';
import * as util from 'util';
import _ from 'lodash';
import util from 'util';

let loggerInstance;

Expand Down
2 changes: 1 addition & 1 deletion src/path-rewriter.ts
@@ -1,4 +1,4 @@
import * as _ from 'lodash';
import _ from 'lodash';
import { ERRORS } from './errors';
import { getInstance } from './logger';
const logger = getInstance();
Expand Down
2 changes: 1 addition & 1 deletion src/router.ts
@@ -1,4 +1,4 @@
import * as _ from 'lodash';
import _ from 'lodash';
import { getInstance } from './logger';
const logger = getInstance();

Expand Down
59 changes: 59 additions & 0 deletions src/types.ts
@@ -0,0 +1,59 @@
import express from 'express';
import http from 'http';
import httpProxy from 'http-proxy';
import net from 'net';

export interface IRequest extends express.Request {}
export interface IResponse extends express.Response {}

export interface IRequestHandler extends express.RequestHandler {
upgrade?: (req: IRequest, socket: net.Socket, head: any) => void;
}

export type Filter =
| string
| string[]
| ((pathname: string, req: IRequest) => boolean);

export interface Options extends httpProxy.ServerOptions {
pathRewrite?:
| { [regexp: string]: string }
| ((path: string, req: IRequest) => string);
router?:
| { [hostOrPath: string]: string }
| ((req: IRequest) => string)
| ((req: IRequest) => Promise<string>);
logLevel?: 'debug' | 'info' | 'warn' | 'error' | 'silent';
logProvider?(provider: LogProvider): LogProvider;

onError?(err: Error, req: IRequest, res: IResponse): void;
onProxyRes?(
proxyRes: http.ServerResponse,
req: IRequest,
res: IResponse
): void;
onProxyReq?(
proxyReq: http.ClientRequest,
req: IRequest,
res: IResponse
): void;
onProxyReqWs?(
proxyReq: http.ClientRequest,
req: IRequest,
socket: net.Socket,
options: httpProxy.ServerOptions,
head: any
): void;
onOpen?(proxySocket: net.Socket): void;
onClose?(res: IResponse, socket: net.Socket, head: any): void;
}

interface LogProvider {
log: Logger;
debug?: Logger;
info?: Logger;
warn?: Logger;
error?: Logger;
}

type Logger = (...args: any[]) => void;
2 changes: 1 addition & 1 deletion test/e2e/_utils.ts
@@ -1,4 +1,4 @@
import * as express from 'express';
import express from 'express';

// tslint:disable-next-line: no-var-requires
export const proxyMiddleware = require('../../dist/index');
Expand Down
4 changes: 2 additions & 2 deletions test/e2e/express-router.spec.ts
@@ -1,5 +1,5 @@
import * as express from 'express';
import * as http from 'http';
import express from 'express';
import http from 'http';
import { proxyMiddleware as proxy } from './_utils';

describe('Usage in Express', () => {
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/http-proxy-middleware.spec.ts
@@ -1,4 +1,4 @@
import * as http from 'http';
import http from 'http';
import { createServer, proxyMiddleware } from './_utils';

describe('E2E http-proxy-middleware', () => {
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/path-rewriter.spec.ts
@@ -1,4 +1,4 @@
import * as http from 'http';
import http from 'http';
import { createServer, proxyMiddleware } from './_utils';

describe('E2E pathRewrite', () => {
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/router.spec.ts
@@ -1,4 +1,4 @@
import * as http from 'http';
import http from 'http';
import { createServer, proxyMiddleware } from './_utils';

describe('E2E router', () => {
Expand Down
4 changes: 2 additions & 2 deletions test/e2e/websocket.spec.ts
@@ -1,5 +1,5 @@
import * as http from 'http';
import * as WebSocket from 'ws';
import http from 'http';
import WebSocket from 'ws';
// tslint:disable-next-line: no-duplicate-imports
import { Server as WebSocketServer } from 'ws';
import { createServer, proxyMiddleware } from './_utils';
Expand Down