untitled paste

unlisted ⁨2⁩ ⁨files⁩ 2023-05-24 08:59:42 UTC

workers.js

Raw
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
  }
}

workers2.js

Raw
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
    }
  }
}