fet-block
Version:
fetBlock is a web h5 request hook library
98 lines (92 loc) • 3.68 kB
JavaScript
import { nativeXhrRequest, standardizationRequestOptions } from "../../tools/xhr";
import { getUAInfo, getLocalStorageObject } from "../../tools/dom";
import { getUrlDomain } from "../../tools/url";
import { getAllTunnelTypes, isCanIUseThisTunnel } from "../tunnels/index";
import { printDebugLog } from "../../tools/log";
let configJsonUrl = process.env.NODE_ENV === 'production'
? `https://www.unpkg.com/fet@${pkgVersion}/dist/config.json`
: '/dist/config.json'
if (window.fetBlockConfigUrl) configJsonUrl = window.fetBlockConfigUrl
const LOCAL_STORAGE_FET_BLOCK_CONFIG_KEY = 'fet_block_config_json'
let isFirstInitFlag = true;
const FET_BLOCK_CONFIG = {
originConfig: {},
userProperty: {},
finalRules: {}
}
// 获取该用户属性所映射出的最终配置,且结构为 domain: [rule, rule]
function getConfigByUser(originConfig, userProperty) {
const configMap = originConfig[userProperty.lang]
for (const key in configMap) {
if (configMap[key] && typeof configMap[key] === 'string') {
configMap[key] = [configMap[key]]
}
}
return configMap
}
export async function init() {
printDebugLog('init rulesManager')
// 1. 拿出本地config配置
const config = getLocalStorageObject(LOCAL_STORAGE_FET_BLOCK_CONFIG_KEY)
if (config) {
FET_BLOCK_CONFIG.originConfig = config
}
// 2. 计算出用户自身属性
FET_BLOCK_CONFIG.userProperty = {
lang: getUAInfo().lang
}
// 3.计算出当前用户属性所对应的最终配置
// 若配置支持运营商/特殊uid等粒度,则需要对配置进行merge处理。此处暂时省略。
// 这里暂且只做一个 country 级别的计算
FET_BLOCK_CONFIG.finalRules = getConfigByUser(FET_BLOCK_CONFIG.originConfig, FET_BLOCK_CONFIG.userProperty) || {}
window.FET_BLOCK_CONFIG = FET_BLOCK_CONFIG
// 4. 异步拉取远程最新配置
if (isFirstInitFlag) {
isFirstInitFlag = false;
const res = await nativeXhrRequest({
url: configJsonUrl
})
localStorage.setItem(LOCAL_STORAGE_FET_BLOCK_CONFIG_KEY, res?.body)
init()
}
}
// 根据请求参数,找出该url命中的最佳规则. 最佳规则结构:{type: 'tunnel' | 'xhr', targetUrl: string}
export function getRuleByRequestUrl(reqOptions, isForceXHR) {
const standardizationReqOptions = standardizationRequestOptions(reqOptions)
const { finalRules } = FET_BLOCK_CONFIG
// 1. 基于域名找出规则数组
const domain = getUrlDomain(standardizationReqOptions?.url)
const domainRules = finalRules[domain]
if (!domainRules) {
return {
type: 'xhr',
targetUrl: standardizationReqOptions?.url
}
}
// 2. 遍历所有规则,找到第一个匹配的返回
let bestRule = null
for (const rule of domainRules) {
if (getAllTunnelTypes().includes(rule)) {
if (isCanIUseThisTunnel(rule) && !isForceXHR) {
bestRule = {
type: 'tunnel',
targetUrl: standardizationReqOptions?.url,
tunnelApi: rule
}
}
else {
continue
}
}
else {
bestRule = {
type: 'xhr',
targetUrl: standardizationReqOptions?.url?.replace(domain, rule)
}
}
return bestRule
}
}
export function getDomainReplaceRuleByRequestUrl(reqOptions) {
return getRuleByRequestUrl(reqOptions, true)
}