addEventListener('fetch', event => { let curObj = undefined // 初始化为 undefined const request = event.request const headersArray = Array.from(request.headers) // 获得 [name, value] 数组 const mutableHeaders = new Headers(headersArray) // 构造 Headers 对象 mutableHeaders.set('User-Agent', 'My User Agent String') // 设置 User-Agent const newRequest = new Request(request, {headers: mutableHeaders}) // 构造新请求 event.respondWith( fetch(newRequest) .then(response => { if (response.status === 200) return response return undefined }) .catch(() => Response.ok()) ) function checkResponse(response) { if (response.status != 200) { return undefined } return response .catch(() => Response.ok()) } }) async function handleRequest(request) { const url = new URL(request.url) const originalYamlUrl = url.searchParams.get('originalYaml') const modifierYamlUrl = url.searchParams.get('modifierYaml') let origYamlResponse const originalYamlResponse = await fetch(originalYamlUrl) .catch(() => { origYamlResponse = undefined }) console.log(originalYamlResponse) // 打印 originalYamlResponse let modYamlResponse const modifierYamlResponse = await fetch(modifierYamlUrl) .catch(() => { modYamlResponse = undefined }) console.log(modifierYamlResponse) // 打印 modifierYamlResponse const [originalYamlText, modifierYamlText] = await Promise.all([ originalYamlResponse.text(), modifierYamlResponse.text() ]) const originalYaml = parseYAML(originalYamlText) const modifierYaml = parseYAML(modifierYamlText) applyModifications(originalYaml, modifierYaml) const modifiedYamlText = serializeYAML(originalYaml) return new Response(modifiedYamlText, {headers: {'Content-Type': 'text/plain'}}) } function parseYAML(yaml) { // 简单的 YAML 解析器 let obj let curObj = obj let arrObj let indent = 0 yaml.split('\n').forEach(line => { if (line.match(/^\s*- /)) { // 数组项 if (indent > 0) arrObj.push(curObj) curObj = {} indent++ } else if (line.match(/^\s*[a-z0-9_]+:/)) { // 对象属性 const parts = line.split(': ') curObj[parts[0]] = parseValue(parts[1]) } else if (line.match(/^\s*-$/)) { // 数组结束 curObj = arrObj indent-- arrObj = null } else if (line.match(/^\s+$/)) { // 空行,忽略 } else if (line.match(/^\s+[^-]/)) { // 属于上一层,返回上一层 curObj = curObj.parent indent-- } else { throw new Error('Unsupported YAML line: ' + line) } }) return obj } function serializeYAML(obj) { // YAML 序列化器 let yaml = '' const serializeObj = (obj) => { Object.keys(obj).forEach(key => { yaml += `${key}:` const value = obj[key] if (Array.isArray(value)) { yaml += '\n' value.forEach(v => serializeObj(v)) yaml += '- ' } else if (typeof value === 'object') { yaml += '\n' serializeObj(value) } else { yaml += ` ${value}\n` } }) } serializeObj(obj) return yaml } function applyModifications(originalYaml, modifierYaml) { const keys = [ "append-rules", "prepend-rules", "append-proxies", "prepend-proxies", "append-proxy-groups", "prepend-proxy-groups", "mix-proxy-providers", "mix-rule-providers", "mix-object", "commands", ]; keys.forEach((key) => { if (modifierYaml.hasOwnProperty(key)) { switch (key) { case "append-rules": case "append-proxies": case "append-proxy-groups": originalYaml[key.replace("append-", "")].push(...modifierYaml[key]); break; case "prepend-rules": case "prepend-proxies": case "prepend-proxy-groups": originalYaml[key.replace("prepend-", "")].unshift(...modifierYaml[key]); break; case "mix-proxy-providers": case "mix-rule-providers": case "mix-object": Object.assign(originalYaml[key.replace("mix-", "")], modifierYaml[key]); break; case "commands": applyCommands(originalYaml, modifierYaml[key]); break; } } }); } function applyCommands(originalYaml, commands) { for (let i = 0; i < commands.length; i++) { const parts = commands[i].split('.') let target = originalYaml for (let j = 0; j < parts.length - 1; j++) { const part = parts[j] if (part.match(/^\d+$/)) { target = target[parseInt(part)] } else { target = target[part] } } const lastPart = parts[parts.length - 1] const cmdParts = lastPart.split(/([=+-])/) const cmd = cmdParts[1] const value = cmdParts[2] switch (cmd) { case '=': target[cmdParts[0]] = parseValue(value) break case '+': target[cmdParts[0]].push(parseValue(value)) break case '-': target.splice(cmdParts[0], 1) break } } } function parseValue(value) { if (value === 'true') return true if (value === 'false') return false if (!isNaN(value)) return parseInt(value) try { return JSON.parse(value) } catch (err) { return value } }