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
}
}
import { parse as parseYAML, stringify as serializeYAML } from 'yaml';
addEventListener('fetch', event => {
const { request } = event;
// 检查 User-Agent 是否为空
const userAgent = request.headers.get('User-Agent');
if (!userAgent) {
event.respondWith(
new Response('User-Agent is required', { status: 400 })
);
return;
}
event.respondWith(handleRequest(request));
});
async function handleRequest(request) {
// 获取原始 YAML 和修改器 YAML 的 URL
const url = new URL(request.url);
const originalYamlUrl = url.searchParams.get('originalYaml');
const modifierYamlUrl = url.searchParams.get('modifierYaml');
// 获取原始 YAML 和修改器 YAML 的文本
const [originalYamlText, modifierYamlText] = await Promise.all([
fetch(originalYamlUrl).then(res => res.text()),
fetch(modifierYamlUrl).then(res => res.text())
]);
// 解析 YAML
const originalYaml = parseYAML(originalYamlText);
const modifierYaml = parseYAML(modifierYamlText);
// 应用修改
applyModifications(originalYaml, modifierYaml);
// 序列化修改后的 YAML
const modifiedYamlText = serializeYAML(originalYaml);
// 返回修改后的 YAML
return new Response(modifiedYamlText, {
headers: { 'Content-Type': 'text/plain' }
});
}
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
}
}
}