Skip to content

Commit

Permalink
perf: 优化 w2 规则处理
Browse files Browse the repository at this point in the history
  • Loading branch information
renxia committed Mar 6, 2024
1 parent a2d3e56 commit 34d9913
Show file tree
Hide file tree
Showing 6 changed files with 46 additions and 28 deletions.
21 changes: 12 additions & 9 deletions src/lib/ruleHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* @Author: renxia
* @Date: 2024-01-10 16:58:26
* @LastEditors: renxia
* @LastEditTime: 2024-02-29 22:13:44
* @LastEditTime: 2024-03-05 15:33:27
* @Description: 基于 whistle 的 cookie 自动抓取插件
*/

Expand Down Expand Up @@ -35,15 +35,18 @@ function ruleMatcher({ rule, req }: RuleHandlerOptions) {
// url match
if (!errmsg) {
const { url } = req.originalReq;
if (typeof rule.url === 'function') {
if (!rule.url(url, method, req.headers)) errmsg = '[func] url match failed';
} else if (rule.url instanceof RegExp) {
if (!rule.url.test(url)) errmsg = '[RegExp] url match failed';
} else if (typeof rule.url === 'string') {
if (url !== rule.url && !micromatch.isMatch(url, rule.url)) {
errmsg = `url ${url} not match rule.url ${color.cyan(rule.url)}`;
const urlMatchList = Array.isArray(rule.url) ? rule.url : [rule.url];
const isUrlMatch = urlMatchList.some(ruleUrl => {
if (typeof ruleUrl === 'function') {
return ruleUrl(url, method, req.headers);
} else if (ruleUrl instanceof RegExp) {
return ruleUrl.test(url);
} else if (typeof ruleUrl === 'string') {
return url == ruleUrl || micromatch.isMatch(url, ruleUrl);
}
}
});

if (!isUrlMatch) errmsg = `[url] ${url} not match rule.url`;
}

if (errmsg) {
Expand Down
9 changes: 3 additions & 6 deletions src/lib/rulesManage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ function ruleFormat(rule: RuleItem) {
return false;
}

if (rule.method == null) rule.method = 'post';

if (!rule.ruleId) {
rule.ruleId = `${rule.desc || rule.url}_${rule.method || ''}`;
logger.log(`未设置 ruleId 参数,采用 desc/url + method。[${rule.ruleId}]`);
Expand All @@ -29,8 +31,6 @@ function ruleFormat(rule: RuleItem) {
rule.on = ruleOn;
}

if (rule.method == null) rule.method = 'post';

if (!rule.desc) rule.desc = `${rule.ruleId}_${rule.url || rule.method}`;

if (!rule.mitm && typeof rule.url === 'string') {
Expand All @@ -40,10 +40,7 @@ function ruleFormat(rule: RuleItem) {

if (rule.mitm) {
if (!Array.isArray(rule.mitm)) rule.mitm = [rule.mitm];
rule.mitm = rule.mitm.filter(Boolean).map(d => {
if (typeof d === 'string' && d.includes('*')) return new RegExp(d.replace(/\*+/g, '([a-z:]+)'));
return d;
});
rule.mitm = rule.mitm.filter(d => d && (typeof d === 'string' || d instanceof RegExp));
}

return rule;
Expand Down
5 changes: 4 additions & 1 deletion src/lib/update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* @Author: renxia
* @Date: 2024-01-11 13:38:34
* @LastEditors: renxia
* @LastEditTime: 2024-02-04 22:16:42
* @LastEditTime: 2024-03-06 16:28:59
* @Description:
*/
import fs from 'node:fs';
Expand Down Expand Up @@ -43,6 +43,9 @@ export async function updateToQlEnvConfig({ name, value, desc }: EnvConfig, upda
if (updateEnvValue instanceof RegExp) params.value = updateEnvValueByRegExp(updateEnvValue, { name, value, desc }, item.value);
else params.value = await updateEnvValue({ name, value }, item.value, X);
if (!params.value) return;
} else if (value.includes('##') && item.value.includes('##')) {
// 支持配置以 ## 隔离 uid
params.value = updateEnvValueByRegExp(/##([a-z0-9_\-*]+)/i, { name, value, desc }, item.value);
}

params.id = item.id;
Expand Down
29 changes: 21 additions & 8 deletions src/lib/w2RulesManage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* @Author: renxia
* @Date: 2024-01-22 14:00:13
* @LastEditors: renxia
* @LastEditTime: 2024-03-01 16:41:28
* @LastEditTime: 2024-03-04 22:48:50
* @Description:
*/
import { existsSync, readFileSync } from 'node:fs';
Expand Down Expand Up @@ -119,14 +119,27 @@ export function loadW2Rules(whistleRules: WhistleRuleItem[], action: 'clear' | '
}
}

const cache = {
w2Rules: {
value: '',
update: 0,
},
};
export function getW2Rules() {
const rulesSet = new Set<string>();
const values = {} as W2RuleMapItem['values'];
const now = Date.now();

rulesMap.forEach(item => {
item.rules.forEach(r => rulesSet.add(r));
Object.assign(values, item.values);
});
// 30s 缓存
if (now - cache.w2Rules.update > 30_000) {
const rulesSet = new Set<string>();
const values = {} as W2RuleMapItem['values'];

rulesMap.forEach(item => {
item.rules.forEach(r => rulesSet.add(r));
Object.assign(values, item.values);
});

cache.w2Rules.value = JSON.stringify({ rules: [...rulesSet].join('\n').replace(/#.+\n?/gm, ''), values });
}

return JSON.stringify({ rules: [...rulesSet].join('\n'), values });
return cache.w2Rules.value;
}
2 changes: 1 addition & 1 deletion src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export default (server: Whistle.PluginServer, options: Whistle.PluginOptions) =>
const r = await ruleHandler({ req, rule, res });
if (r.body != null) return res.end(util.toBuffer(r.body) || '');
} catch (e) {
logger.error('[ruleHandler]err', rule.ruleId, e);
logger.error(`[ruleHandler][${color.red(rule.ruleId)}]err`, e);
}
}
}
Expand Down
8 changes: 5 additions & 3 deletions typings/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ export type RuleRunOnType = 'req-header' | 'req-body' | 'res-body';

type PromiseMaybe<T> = T | Promise<T>;

type RuleUrlItem = string | RegExp | ((url: string, method: string, headers: IncomingHttpHeaders) => boolean);

export interface RuleItem {
/** 规则 id,唯一标记 */
ruleId: string;
Expand All @@ -95,15 +97,15 @@ export interface RuleItem {
on?: RuleRunOnType;
/** 禁用该规则 */
disabled?: boolean;
/**
/**
* MITM 域名匹配配置。
* 当 res-body 类型的规则命中时会主动启用 https 解析拦截(whistle 未启用 https 拦截时)。
* 若 url 参数以 https:// 开头,则从其提取 host 域名配置部分作为 mitm 默认值。
* 推荐配置该项以选择性的启用 https 拦截,以提升 whistle 代理性能与效率。
*/
mitm?: string | RegExp | (string | RegExp)[];
/** url 匹配规则 */
url?: string | RegExp | ((url: string, method: string, headers: IncomingHttpHeaders) => boolean);
url?: RuleUrlItem | RuleUrlItem[];
/** 方法匹配。可选: post、get、put 等。设置为空或 ** 表示全部匹配。若不设置,默认为 post */
method?: string;
/** [envConfig]是否上传至 青龙 环境变量配置。需配置 qlToken */
Expand All @@ -119,7 +121,7 @@ export interface RuleItem {
/** 获取当前用户唯一性的 uid,及自定义需缓存的数据 data(可选) */
getCacheUid?: string | ((ctx: RuleHandlerParams) => string | { uid: string; data: any } | undefined);
/** [envConfig]更新处理已存在的环境变量,返回合并后的结果。若无需修改则可返回空 */
updateEnvValue?: (envConfig: EnvConfig, oldValue: string, X: RuleHandlerParams['X']) => string | undefined;
updateEnvValue?: ((envConfig: EnvConfig, oldValue: string, X: RuleHandlerParams['X']) => string | undefined) | RegExp;
/** <${type}>handler 简写。根据 type 类型自动识别 */
handler?: (ctx: RuleHandlerParams) => PromiseMaybe<RuleHandlerResult>;
// /** 规则处理并返回环境变量配置。可以数组的形式返回多个 */
Expand Down

0 comments on commit 34d9913

Please sign in to comment.