feat: refact the remaining files into TS

This commit is contained in:
砚然 2018-08-31 17:40:30 +08:00
parent bcb7451579
commit 0385096857
12 changed files with 310 additions and 252 deletions

View File

@ -8,11 +8,13 @@ import util from './util';
import logUtil from './log';
declare interface ICertMgr {
ifRootCAFileExists?: boolean;
generateRootCA?: ( cb: (error: boolean, keyPath: string, crtPath: string) => void ) => void;
getCAStatus?: () => Generator;
trustRootCA?: () => Generator;
getRootCAFilePath?: () => string;
ifRootCAFileExists?: () => boolean;
isRootCAFileExists?: () => boolean;
getRootDirPath?: () => string;
getCertificate?: (serverName: string, cb: (err: Error, key: string, crt: string) => void) => void;
}

15
lib/proxy/index.ts Normal file
View File

@ -0,0 +1,15 @@
import ProxyCore from './proxyCore';
import ProxyServer from './proxyServer';
import WebInterface from '../webInterface';
import Recorder from '../recorder';
import certMgr from '../certMgr';
module.exports.ProxyCore = ProxyCore;
module.exports.ProxyServer = ProxyServer;
module.exports.ProxyRecorder = Recorder;
module.exports.ProxyWebServer = WebInterface;
module.exports.utils = {
systemProxyMgr: require('../systemProxyMgr'),
certMgr,
};

View File

@ -1,41 +1,28 @@
'use strict';
/*tslint:disable:max-line-length */
const http = require('http'),
https = require('https'),
async = require('async'),
color = require('colorful'),
certMgr = require('./certMgr').default,
Recorder = require('./recorder').default,
logUtil = require('./log').default,
util = require('./util').default,
events = require('events'),
co = require('co'),
WebInterface = require('./webInterface'),
wsServerMgr = require('./wsServerMgr').default,
ThrottleGroup = require('stream-throttle').ThrottleGroup;
import * as http from 'http';
import * as https from 'https';
import * as async from 'async';
import * as color from 'colorful';
import * as events from 'events';
import * as throttle from 'stream-throttle';
import * as co from 'co';
import certMgr from '../certMgr';
import Recorder from '../recorder';
import logUtil from '../log';
import util from '../util';
import RequestHandler from '../requestHandler';
import wsServerMgr from '../wsServerMgr';
import WebInterface from '../webInterface';
// const memwatch = require('memwatch-next');
declare type TSyncTaskCb = (err: Error) => void;
// setInterval(() => {
// console.log(process.memoryUsage());
// const rss = Math.ceil(process.memoryUsage().rss / 1000 / 1000);
// console.log('Program is using ' + rss + ' mb of Heap.');
// }, 1000);
const ThrottleGroup = throttle.ThrottleGroup;
// memwatch.on('stats', (info) => {
// console.log('gc !!');
// console.log(process.memoryUsage());
// const rss = Math.ceil(process.memoryUsage().rss / 1000 / 1000);
// console.log('GC !! Program is using ' + rss + ' mb of Heap.');
// // var heapUsed = Math.ceil(process.memoryUsage().heapUsed / 1000);
// // console.log("Program is using " + heapUsed + " kb of Heap.");
// // console.log(info);
// });
const T_TYPE_HTTP = 'http',
T_TYPE_HTTPS = 'https',
DEFAULT_TYPE = T_TYPE_HTTP;
const T_TYPE_HTTP = 'http';
const T_TYPE_HTTPS = 'https';
const DEFAULT_TYPE = T_TYPE_HTTP;
const PROXY_STATUS_INIT = 'INIT';
const PROXY_STATUS_READY = 'READY';
@ -47,25 +34,24 @@ const PROXY_STATUS_CLOSED = 'CLOSED';
* @extends {events.EventEmitter}
*/
class ProxyCore extends events.EventEmitter {
private socketIndex: number;
private status: 'INIT' | 'READY' | 'CLOSED';
private proxyPort: string;
private proxyType: 'http' | 'https';
protected proxyHostName: string;
public recorder: Recorder;
private httpProxyServer: http.Server | https.Server;
protected webServerInstance: WebInterface;
private requestHandler: RequestHandler;
private proxyRule: AnyProxyRule;
private socketPool: {
[key: string]: http.IncomingMessage;
};
/**
* Creates an instance of ProxyCore.
*
* @param {object} config - configs
* @param {number} config.port - port of the proxy server
* @param {object} [config.rule=null] - rule module to use
* @param {string} [config.type=http] - type of the proxy server, could be 'http' or 'https'
* @param {strign} [config.hostname=localhost] - host name of the proxy server, required when this is an https proxy
* @param {number} [config.throttle] - speed limit in kb/s
* @param {boolean} [config.forceProxyHttps=false] - if proxy all https requests
* @param {boolean} [config.silent=false] - if keep the console silent
* @param {boolean} [config.dangerouslyIgnoreUnauthorized=false] - if ignore unauthorized server response
* @param {object} [config.recorder] - recorder to use
* @param {boolean} [config.wsIntercept] - whether intercept websocket
*
* @memberOf ProxyCore
*/
constructor(config) {
constructor(config: AnyProxyConfig) {
super();
config = config || {};
@ -114,12 +100,12 @@ class ProxyCore extends events.EventEmitter {
this.recorder = config.recorder;
// init request handler
const RequestHandler = util.freshRequire('./requestHandler').default;
this.requestHandler = new RequestHandler({
const RequestHandlerClass = (util.freshRequire('./requestHandler') as any).default;
this.requestHandler = new RequestHandlerClass({
wsIntercept: config.wsIntercept,
httpServerPort: config.port, // the http server port for http proxy
forceProxyHttps: !!config.forceProxyHttps,
dangerouslyIgnoreUnauthorized: !!config.dangerouslyIgnoreUnauthorized
dangerouslyIgnoreUnauthorized: !!config.dangerouslyIgnoreUnauthorized,
}, this.proxyRule, this.recorder);
}
@ -133,7 +119,7 @@ class ProxyCore extends events.EventEmitter {
* @returns undefined
* @memberOf ProxyCore
*/
handleExistConnections(socket) {
private handleExistConnections(socket: http.IncomingMessage): void {
const self = this;
self.socketIndex ++;
const key = `socketIndex_${self.socketIndex}`;
@ -151,7 +137,7 @@ class ProxyCore extends events.EventEmitter {
*
* @memberOf ProxyCore
*/
start() {
public start(): ProxyCore {
const self = this;
self.socketIndex = 0;
self.socketPool = {};
@ -162,7 +148,7 @@ class ProxyCore extends events.EventEmitter {
async.series(
[
// creat proxy server
function (callback) {
function(callback: TSyncTaskCb): void {
if (self.proxyType === T_TYPE_HTTPS) {
certMgr.getCertificate(self.proxyHostName, (err, keyContent, crtContent) => {
if (err) {
@ -170,7 +156,7 @@ class ProxyCore extends events.EventEmitter {
} else {
self.httpProxyServer = https.createServer({
key: keyContent,
cert: crtContent
cert: crtContent,
}, self.requestHandler.userRequestHandler);
callback(null);
}
@ -182,16 +168,16 @@ class ProxyCore extends events.EventEmitter {
},
// handle CONNECT request for https over http
function (callback) {
function(callback: TSyncTaskCb): void {
self.httpProxyServer.on('connect', self.requestHandler.connectReqHandler);
callback(null);
},
function (callback) {
function(callback: TSyncTaskCb): void {
wsServerMgr.getWsServer({
server: self.httpProxyServer,
connHandler: self.requestHandler.wsHandler
connHandler: self.requestHandler.wsHandler,
});
// remember all sockets, so we can destory them when call the method 'close';
self.httpProxyServer.on('connection', (socket) => {
@ -201,7 +187,7 @@ class ProxyCore extends events.EventEmitter {
},
// start proxy server
function (callback) {
function(callback: TSyncTaskCb): void {
self.httpProxyServer.listen(self.proxyPort);
callback(null);
},
@ -221,7 +207,7 @@ class ProxyCore extends events.EventEmitter {
let ruleSummaryString = '';
const ruleSummary = this.proxyRule.summary;
if (ruleSummary) {
co(function *() {
co(function *(): Generator {
if (typeof ruleSummary === 'string') {
ruleSummaryString = ruleSummary;
} else {
@ -239,10 +225,10 @@ class ProxyCore extends events.EventEmitter {
logUtil.printLog(color.red(tipText), logUtil.T_ERR);
logUtil.printLog(err, logUtil.T_ERR);
self.emit('error', {
error: err
error: err,
});
}
}
},
);
return self;
@ -256,24 +242,34 @@ class ProxyCore extends events.EventEmitter {
*
* @memberOf ProxyCore
*/
close() {
public close(): Promise<Error> {
// clear recorder cache
return new Promise((resolve) => {
if (this.httpProxyServer) {
// destroy conns & cltSockets when closing proxy server
for (const connItem of this.requestHandler.conns) {
const key = connItem[0];
const conn = connItem[1];
this.requestHandler.conns.forEach((conn, key) => {
logUtil.printLog(`destorying https connection : ${key}`);
conn.end();
}
});
for (const cltSocketItem of this.requestHandler.cltSockets) {
const key = cltSocketItem[0];
const cltSocket = cltSocketItem[1];
this.requestHandler.cltSockets.forEach((cltSocket, key) => {
logUtil.printLog(`endding https cltSocket : ${key}`);
cltSocket.end();
}
});
// for (const connItem of this.requestHandler.conns) {
// const key = connItem[0];
// const conn = connItem[1];
// logUtil.printLog(`destorying https connection : ${key}`);
// conn.end();
// }
// for (const cltSocketItem of this.requestHandler.cltSockets) {
// const key = cltSocketItem[0];
// const cltSocket = cltSocketItem[1];
// logUtil.printLog(`endding https cltSocket : ${key}`);
// cltSocket.end();
// }
if (this.socketPool) {
for (const key in this.socketPool) {
@ -296,92 +292,8 @@ class ProxyCore extends events.EventEmitter {
} else {
resolve();
}
})
}
}
/**
* start proxy server as well as recorder and webInterface
*/
class ProxyServer extends ProxyCore {
/**
*
* @param {object} config - config
* @param {object} [config.webInterface] - config of the web interface
* @param {boolean} [config.webInterface.enable=false] - if web interface is enabled
* @param {number} [config.webInterface.webPort=8002] - http port of the web interface
*/
constructor(config) {
// prepare a recorder
const recorder = new Recorder();
const configForCore = Object.assign({
recorder,
}, config);
super(configForCore);
this.proxyWebinterfaceConfig = config.webInterface;
this.recorder = recorder;
this.webServerInstance = null;
}
start() {
// start web interface if neeeded
if (this.proxyWebinterfaceConfig && this.proxyWebinterfaceConfig.enable) {
this.webServerInstance = new WebInterface(this.proxyWebinterfaceConfig, this.recorder);
// start web server
this.webServerInstance.start().then(() => {
// start proxy core
super.start();
})
.catch((e) => {
this.emit('error', e);
});
} else {
super.start();
}
}
close() {
return new Promise((resolve, reject) => {
super.close()
.then((error) => {
if (error) {
resolve(error);
}
});
if (this.recorder) {
logUtil.printLog('clearing cache file...');
this.recorder.clear();
}
const tmpWebServer = this.webServerInstance;
this.recorder = null;
this.webServerInstance = null;
if (tmpWebServer) {
logUtil.printLog('closing webserver...');
tmpWebServer.close((error) => {
if (error) {
console.error(error);
logUtil.printLog(`proxy web server close FAILED: ${error.message}`, logUtil.T_ERR);
} else {
logUtil.printLog(`proxy web server closed at ${this.proxyHostName} : ${this.webPort}`);
}
resolve(error);
})
} else {
resolve(null);
}
});
}
}
module.exports.ProxyCore = ProxyCore;
module.exports.ProxyServer = ProxyServer;
module.exports.ProxyRecorder = Recorder;
module.exports.ProxyWebServer = WebInterface;
module.exports.utils = {
systemProxyMgr: require('./systemProxyMgr'),
certMgr,
};
export default ProxyCore;

87
lib/proxy/proxyServer.ts Normal file
View File

@ -0,0 +1,87 @@
'use strict';
import ProxyCore from './proxyCore.js';
import Recorder from '../recorder';
import WebInterface from '../webInterface';
import logUtil from '../log';
/**
* start proxy server as well as recorder and webInterface
*/
class ProxyServer extends ProxyCore {
public proxyWebinterfaceConfig: any;
/**
*
* @param {object} config - config
* @param {object} [config.webInterface] - config of the web interface
* @param {boolean} [config.webInterface.enable=false] - if web interface is enabled
* @param {number} [config.webInterface.webPort=8002] - http port of the web interface
*/
constructor(config: AnyProxyConfig) {
// prepare a recorder
const recorder = new Recorder();
const configForCore = Object.assign({
recorder,
}, config);
super(configForCore);
this.proxyWebinterfaceConfig = config.webInterface;
this.recorder = recorder;
this.webServerInstance = null;
}
public start(): ProxyServer {
// start web interface if neeeded
if (this.proxyWebinterfaceConfig && this.proxyWebinterfaceConfig.enable) {
this.webServerInstance = new WebInterface(this.proxyWebinterfaceConfig, this.recorder);
// start web server
this.webServerInstance.start().then(() => {
// start proxy core
super.start();
})
.catch((e) => {
this.emit('error', e);
});
} else {
super.start();
}
return this;
}
public close(): Promise<Error> {
return new Promise((resolve, reject) => {
super.close()
.then((error) => {
if (error) {
resolve(error);
}
});
if (this.recorder) {
logUtil.printLog('clearing cache file...');
this.recorder.clear();
}
const tmpWebServer = this.webServerInstance;
this.recorder = null;
this.webServerInstance = null;
if (tmpWebServer) {
logUtil.printLog('closing webserver...');
tmpWebServer.close((error) => {
if (error) {
console.error(error);
logUtil.printLog(`proxy web server close FAILED: ${error.message}`, logUtil.T_ERR);
} else {
logUtil.printLog(`proxy web server closed at ${this.proxyHostName} : ${this.proxyWebinterfaceConfig.webPort}`);
}
resolve(error);
});
} else {
resolve(null);
}
});
}
}
export default ProxyServer;

View File

@ -412,9 +412,11 @@ class RequestHandler {
public dangerouslyIgnoreUnauthorized: boolean;
public httpServerPort: string;
public wsIntercept: boolean;
public conns: Map<string, net.Socket>;
public cltSockets: Map<string, net.Socket>;
public connectReqHandler: () => void;
private userRequestHandler: () => void;
private wsHandler: (wsClient: WebSocket, wsReq: http.IncomingMessage) => void;
public userRequestHandler: () => void;
public wsHandler: (wsClient: WebSocket, wsReq: http.IncomingMessage) => void;
private httpsServerMgr: HttpsServerMgr;
/**
* Creates an instance of RequestHandler.

View File

@ -309,7 +309,7 @@ function isFunc(source: object): boolean {
* @param {object} content
* @returns the size of the content
*/
function getByteSize(content: Buffer): number {
function getByteSize(content: Buffer | string): number {
return Buffer.byteLength(content);
}

View File

@ -2,22 +2,44 @@
const DEFAULT_WEB_PORT = 8002; // port for web interface
const express = require('express'),
url = require('url'),
bodyParser = require('body-parser'),
fs = require('fs'),
path = require('path'),
events = require('events'),
qrCode = require('qrcode-npm'),
util = require('./util').default,
certMgr = require('./certMgr').default,
wsServer = require('./wsServer'),
juicer = require('juicer'),
ip = require('ip'),
compress = require('compression');
import * as express from 'express';
import * as url from 'url';
import * as bodyParser from 'body-parser';
import * as fs from 'fs';
import * as path from 'path';
import * as events from 'events';
import * as qrCode from 'qrcode-npm';
import * as juicer from 'juicer';
import * as ip from 'ip';
import * as http from 'http';
import * as compress from 'compression';
import * as buffer from 'buffer';
import util from './util';
import certMgr from './certMgr';
import WsServer from './wsServer';
import Recorder from './recorder';
import LogUtil from './log';
/*tslint:disable:no-var-requires*/
const packageJson = require('../package.json');
// const express = require('express'),
// url = require('url'),
// bodyParser = require('body-parser'),
// fs = require('fs'),
// path = require('path'),
// events = require('events'),
// qrCode = require('qrcode-npm'),
// util = require('./util').default,
// certMgr = require('./certMgr').default,
// wsServer = require('./wsServer'),
// juicer = require('juicer'),
// ip = require('ip'),
// compress = require('compression');
// const packageJson = require('../package.json');
const Buffer = buffer.Buffer;
const MAX_CONTENT_SIZE = 1024 * 2000; // 2000kb
/**
*
@ -25,18 +47,13 @@ const MAX_CONTENT_SIZE = 1024 * 2000; // 2000kb
* @class webInterface
* @extends {events.EventEmitter}
*/
class webInterface extends events.EventEmitter {
/**
* Creates an instance of webInterface.
*
* @param {object} config
* @param {number} config.webPort
* @param {object} recorder
*
* @memberOf webInterface
*/
constructor(config, recorder) {
class WebInterface extends events.EventEmitter {
public webPort: number;
private recorder: Recorder;
private app: Express.Application;
private server: http.Server;
private wsServer: WsServer;
constructor(config: AnyProxyWebInterfaceConfig, recorder: Recorder) {
if (!recorder) {
throw new Error('recorder is required for web interface');
}
@ -44,7 +61,7 @@ class webInterface extends events.EventEmitter {
const self = this;
self.webPort = config.webPort || DEFAULT_WEB_PORT;
self.recorder = recorder;
self.config = config || {};
// self.config = config || {};
self.app = this.getServer();
self.server = null;
@ -54,22 +71,22 @@ class webInterface extends events.EventEmitter {
/**
* get the express server
*/
getServer() {
public getServer(): Express.Application {
const self = this;
const recorder = self.recorder;
const ipAddress = ip.address(),
const ipAddress = ip.address();
// userRule = proxyInstance.proxyRule,
webBasePath = 'web';
const webBasePath = 'web';
let ruleSummary = '';
let customMenu = [];
try {
ruleSummary = ''; // userRule.summary();
customMenu = ''; // userRule._getCustomMenu();
} catch (e) { }
customMenu = []; // userRule._getCustomMenu();
} catch (e) { LogUtil.error(e.stack); }
const myAbsAddress = 'http://' + ipAddress + ':' + self.webPort + '/',
staticDir = path.join(__dirname, '../', webBasePath);
const myAbsAddress = 'http://' + ipAddress + ':' + self.webPort + '/';
const staticDir = path.join(__dirname, '../', webBasePath);
const app = express();
app.use(compress()); // invoke gzip
@ -118,21 +135,21 @@ class webInterface extends events.EventEmitter {
if (query && query.id) {
recorder.getDecodedBody(parseInt(query.id, 10), (err, result) => {
// 返回下载信息
const _resDownload = function (isDownload) {
const resDownload = function(isDownload: boolean): void {
isDownload = typeof isDownload === 'boolean' ? isDownload : true;
res.json({
id: query.id,
type: result.type,
method: result.meethod,
method: result.method,
fileName: result.fileName,
ref: `/downloadBody?id=${query.id}&download=${isDownload}&raw=${!isDownload}`
ref: `/downloadBody?id=${query.id}&download=${isDownload}&raw=${!isDownload}`,
});
};
// 返回内容
const _resContent = () => {
if (util.getByteSize(result.content || '') > MAX_CONTENT_SIZE) {
_resDownload(true);
const resContent = () => {
if (util.getByteSize(result.content || Buffer.from('')) > MAX_CONTENT_SIZE) {
resDownload(true);
return;
}
@ -140,7 +157,7 @@ class webInterface extends events.EventEmitter {
id: query.id,
type: result.type,
method: result.method,
resBody: result.content
resBody: result.content,
});
};
@ -151,14 +168,14 @@ class webInterface extends events.EventEmitter {
result.mime.indexOf('text') === 0 ||
// deal with 'application/x-javascript' and 'application/javascript'
result.mime.indexOf('javascript') > -1) {
_resContent();
resContent();
} else if (result.type === 'image') {
_resDownload(false);
resDownload(false);
} else {
_resDownload(true);
resDownload(true);
}
} else {
_resContent();
resContent();
}
});
} else {
@ -203,11 +220,11 @@ class webInterface extends events.EventEmitter {
app.get('/fetchCrtFile', (req, res) => {
res.setHeader('Access-Control-Allow-Origin', '*');
const _crtFilePath = certMgr.getRootCAFilePath();
if (_crtFilePath) {
const crtFilePath = certMgr.getRootCAFilePath();
if (crtFilePath) {
res.setHeader('Content-Type', 'application/x-x509-ca-cert');
res.setHeader('Content-Disposition', 'attachment; filename="rootCA.crt"');
res.end(fs.readFileSync(_crtFilePath, { encoding: null }));
res.end(fs.readFileSync(crtFilePath, { encoding: null }));
} else {
res.setHeader('Content-Type', 'text/html');
res.end('can not file rootCA ,plase use <strong>anyproxy --root</strong> to generate one');
@ -217,35 +234,37 @@ class webInterface extends events.EventEmitter {
// make qr code
app.get('/qr', (req, res) => {
res.setHeader('Access-Control-Allow-Origin', '*');
const qr = qrCode.qrcode(4, 'M'),
targetUrl = myAbsAddress;
const qr = qrCode.qrcode(4, 'M');
const targetUrl = myAbsAddress;
qr.addData(targetUrl);
qr.make();
const qrImageTag = qr.createImgTag(4);
const resDom = '<a href="__url"> __img <br> click or scan qr code to start client </a>'.replace(/__url/, targetUrl).replace(/__img/, qrImageTag);
const resDom = '<a href="__url"> __img <br> click or scan qr code to start client </a>'
.replace(/__url/, targetUrl).replace(/__img/, qrImageTag);
res.setHeader('Content-Type', 'text/html');
res.end(resDom);
});
app.get('/api/getQrCode', (req, res) => {
res.setHeader('Access-Control-Allow-Origin', '*');
const qr = qrCode.qrcode(4, 'M'),
targetUrl = myAbsAddress + 'fetchCrtFile';
const qr = qrCode.qrcode(4, 'M');
const targetUrl = myAbsAddress + 'fetchCrtFile';
qr.addData(targetUrl);
qr.make();
const qrImageTag = qr.createImgTag(4);
// resDom = '<a href="__url"> __img <br> click or scan qr code to download rootCA.crt </a>'.replace(/__url/,targetUrl).replace(/__img/,qrImageTag);
// resDom = '<a href="__url"> __img <br> click or scan qr code to download rootCA.crt </a>'
// .replace(/__url/,targetUrl).replace(/__img/,qrImageTag);
// res.setHeader("Content-Type", "text/html");
// res.end(resDom);
const isRootCAFileExists = certMgr.isRootCAFileExists();
const isRootCAFileExists = certMgr.ifRootCAFileExists();
res.json({
status: 'success',
url: targetUrl,
isRootCAFileExists,
qrImgDom: qrImageTag
qrImgDom: qrImageTag,
});
});
@ -265,7 +284,7 @@ class webInterface extends events.EventEmitter {
ruleSummary: ruleSummary || '',
ipAddress: util.getAllIpAddress(),
port: '', // proxyInstance.proxyPort, // TODO
appVersion: packageJson.version
appVersion: packageJson.version,
});
});
@ -276,23 +295,23 @@ class webInterface extends events.EventEmitter {
certMgr.generateRootCA(() => {
res.json({
status: 'success',
code: 'done'
code: 'done',
});
});
} else {
res.json({
status: 'success',
code: 'root_ca_exists'
code: 'root_ca_exists',
});
}
});
app.use((req, res, next) => {
const indexTpl = fs.readFileSync(path.join(staticDir, '/index.html'), { encoding: 'utf8' }),
opt = {
const indexTpl = fs.readFileSync(path.join(staticDir, '/index.html'), { encoding: 'utf8' });
const opt = {
rule: ruleSummary || '',
customMenu: customMenu || [],
ipAddress: ipAddress || '127.0.0.1'
ipAddress: ipAddress || '127.0.0.1',
};
if (url.parse(req.url).pathname === '/') {
@ -306,25 +325,25 @@ class webInterface extends events.EventEmitter {
return app;
}
start() {
public start(): Promise<undefined> {
const self = this;
return new Promise((resolve, reject) => {
self.server = self.app.listen(self.webPort);
self.wsServer = new wsServer({
server: self.server
self.server = (self.app as any).listen(self.webPort);
self.wsServer = new WsServer({
server: self.server,
}, self.recorder);
self.wsServer.start();
resolve();
})
});
}
close() {
public close(cb: (error: Error) => void): void {
this.server && this.server.close();
this.wsServer && this.wsServer.closeAll();
this.server = null;
this.wsServer = null;
this.proxyInstance = null;
// this.proxyInstance = null;
}
}
module.exports = webInterface;
export default WebInterface;

View File

@ -1,10 +1,11 @@
'use strict';
// websocket server manager
// websocket server manager, for the webinterface websocket handling
import * as WebSocket from 'ws';
import Recorder from './recorder';
import logUtil from './log';
import { Server } from 'http';
import * as http from 'http';
import * as https from 'https';
declare interface IWsMessage {
type?: 'error' | 'body';
@ -18,7 +19,8 @@ declare interface IWsMessage {
}
declare interface IWsServerConfig {
server: Server;
server: http.Server | https.Server;
connHandler?: (wsClient: WebSocket, wsReq: http.IncomingMessage) => void;
}
declare interface IMultiMessageQueue {
@ -198,4 +200,4 @@ class WsServer {
}
}
module.exports = WsServer;
export default WsServer;

View File

@ -1,9 +1,10 @@
/**
* manage the websocket server
* manage the websocket server, for proxy target only
*
*/
import * as ws from 'ws';
import * as http from 'http';
import * as https from 'https';
import logUtil from './log.js';
const WsServer = ws.Server;
@ -15,7 +16,7 @@ const WsServer = ws.Server;
{handler} config.handler
*/
function getWsServer(config: {
server: http.Server;
server: http.Server | https.Server;
connHandler: (wsClient: ws, wsReq: http.IncomingMessage) => void;
}): ws.Server {
const wss = new WsServer({

View File

@ -40,6 +40,7 @@
"ws": "^5.1.0"
},
"devDependencies": {
"@types/express": "^4.16.0",
"@types/node": "^8.10.21",
"@types/ws": "^6.0.0",
"antd": "^2.5.0",

View File

@ -14,6 +14,8 @@
"only-arrow-functions": false,
"no-reference": false,
"forin": false,
"member-ordering": false,
"max-classes-per-file": false,
"typedef": [
true,
"call-signature",

29
typings/index.d.ts vendored
View File

@ -7,17 +7,27 @@ declare module NodeJS {
}
}
declare interface AnyProxyWebInterfaceConfig {
webPort?: number;
}
declare interface AnyProxyConfig {
port: string; // 代理监听端口
httpServerPort: string; // web server 的端口
forceProxyHttps: boolean;
dangerouslyIgnoreUnauthorized: boolean; // 是否忽略https证书
wsIntercept: boolean; // 是否代理websocket
chunkSizeThreshold: number; // throttle的配置
port?: string; // port of the proxy server
httpServerPort?: string; // web server 的端口
type?: 'http' | 'https'; // type of the proxy server
forceProxyHttps?: boolean; // proxy https also
dangerouslyIgnoreUnauthorized?: boolean; // should ignore
wsIntercept?: boolean; // should proxy websocket
throttle?: string; // speed limit in kb/s
hostname?: string; // the hostname of this proxy, default to 'localhost'
recorder?: any; // A Recorder instance
silent?: boolean; // if keep the console silent
rule?: any; // rule module to use
webInterface?: AnyProxyWebInterfaceConfig;
}
declare interface AnyProxyRule {
summary?: string,
summary?: string | Function,
beforeSendRequest?: Function,
beforeSendResponse?: Function,
beforeDealHttpsRequest?: Function,
@ -87,3 +97,8 @@ declare interface IExecScriptResult {
status: number;
stdout?: string;
}
declare module "*.json" {
const value: any;
export default value;
}