zan-proxy
Version:
189 lines (176 loc) • 6.09 kB
text/typescript
import cookieParser from 'cookie';
import http from 'http';
import koa from 'koa';
import koaBodyParser from 'koa-bodyparser';
import koaMount from 'koa-mount';
import koaQs from 'koa-qs';
import koaStatic from 'koa-static';
import path from 'path';
import SocketIO from 'socket.io';
import { Container, Service } from 'typedi';
import PluginManager from '../plugin-manager';
import {
ConfigureService,
HostService,
HttpTrafficService,
MockDataService,
ProfileService,
RuleService,
} from '../services';
import router from './router';
export class Manager {
private httpTrafficService: HttpTrafficService;
private configureService: ConfigureService;
private profileService: ProfileService;
private hostService: HostService;
private mockDataService: MockDataService;
private ruleService: RuleService;
private pluginManager: PluginManager;
private app: koa;
private server: http.Server;
private io: SocketIO;
constructor() {
this.httpTrafficService = Container.get(HttpTrafficService);
this.configureService = Container.get(ConfigureService);
this.profileService = Container.get(ProfileService);
this.hostService = Container.get(HostService);
this.mockDataService = Container.get(MockDataService);
this.ruleService = Container.get(RuleService);
this.pluginManager = Container.get(PluginManager);
// 初始化koa
this.app = new koa();
// query string
koaQs(this.app);
// body解析
this.app.use(
koaBodyParser({
formLimt: '5mb',
jsonLimit: '5mb',
textLimit: '5mb',
}),
);
// 路由
this.app.use(async (ctx, next) => {
// 取用户Id
const cookies = cookieParser.parse(ctx.request.headers.cookie || '');
ctx.userId = cookies.userId || 'root';
await next();
});
this.app.use(router());
// 静态资源服务
this.app.use(koaStatic(path.join(__dirname, '../../../site')));
this.app.use(koaMount('/plugins', this.pluginManager.getUIApp()));
// 创建server
this.server = http.createServer(this.app.callback());
// socketio
this.io = new SocketIO(this.server);
// 初始化socket io
this._initTraffic();
this._initManger();
}
public listen(port) {
// 启动server
this.server.listen(port);
}
// http流量监控界面
private _initTraffic() {
const socket = this.io.of('/httptrafic');
// 客户端发起连接请求
socket.on('connection', client => {
const userId = this._getUserId(client);
client.join(userId);
this.httpTrafficService.incMonitor(userId);
// 推送过滤器,状态
const state = this.httpTrafficService.getStatus(userId);
client.emit('state', state);
const filter = this.httpTrafficService.getFilter(userId);
client.emit('filter', filter);
client.emit('clear');
client.on('disconnect', () => {
this.httpTrafficService.decMonitor(userId);
});
});
// 监听logRespository事件
this.httpTrafficService.on('traffic', (userId, rows) => {
socket.to(userId).emit('rows', rows);
});
// 过滤器改变
this.httpTrafficService.on('filter', (userId, filter) => {
socket.to(userId).emit('filter', filter);
});
// 状态改变
this.httpTrafficService.on('state-change', (userId, state) => {
socket.to(userId).emit('state', state);
});
// 清空
this.httpTrafficService.on('clear', userId => {
socket.to(userId).emit('clear');
const state = this.httpTrafficService.getStatus(userId);
socket.to(userId).emit('state', state);
});
}
// 管理界面 使用的功能
private _initManger() {
const socket = this.io.of('/manager');
// 注册通知
socket.on('connection', async client => {
// 监听内部状态的客户端,这些客户端获取当前生效的host、rule
const userId = this._getUserId(client);
client.join(userId);
// 推送最新数据
// proxy配置
const config = await this.configureService.getConfigure();
client.emit('configure', config);
// 个人配置
const profile = await this.profileService.getProfile(userId);
client.emit('profile', profile);
const mappedClientIps = await this.profileService.getClientIpsMappedToUserId(
userId,
);
client.emit('mappedClientIps', mappedClientIps);
// host文件列表
const hostFileList = await this.hostService.getHostFileList(userId);
client.emit('hostfilelist', hostFileList);
// 规则列表
const ruleFileList = await this.ruleService.getRuleFileList(userId);
client.emit('rulefilelist', ruleFileList);
// 数据文件列表
const dataList = await this.mockDataService.getMockDataList(userId);
client.emit('datalist', dataList);
});
// proxy配置信息
this.configureService.on('data-change', (userId, configure) => {
socket.to(userId).emit('configure', configure);
});
// 个人配置信息
this.profileService.on('data-change-profile', (userId, profile) => {
socket.to(userId).emit('profile', profile);
});
this.profileService.on(
'data-change-clientIpUserMap',
(userId, clientIpList) => {
socket.to(userId).emit('mappedClientIps', clientIpList);
},
);
// host文件变化
this.hostService.on('data-change', (userId, hostFilelist) => {
socket.to(userId).emit('hostfilelist', hostFilelist);
});
// 规则文件列表
this.ruleService.on('data-change', (userId, ruleFilelist) => {
socket.to(userId).emit('rulefilelist', ruleFilelist);
});
// mock文件列表
this.mockDataService.on('data-change', (userId, dataFilelist) => {
socket.to(userId).emit('datalist', dataFilelist);
});
}
// 通用函数,获取web socket连接中的用户id
private _getUserId(socketIOConn) {
const cookies = cookieParser.parse(
socketIOConn.request.headers.cookie || '',
);
return cookies.userId || 'root';
}
}