步骤 2:复制并部署 Worker 脚本
点击 Worker 页面右上角 Edit code,替换全部代码为以下内容并保存部署:
export default {
async fetch(request, env, ctx) {
const url = new URL(request.url);
const corsHeaders = {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, POST, OPTIONS",
"Access-Control-Allow-Headers": "Content-Type, User-Agent",
};
if (request.method === "OPTIONS") {
return new Response(null, { headers: corsHeaders });
}
// 1. 获取订阅内容 (带滑动续期)
if (url.pathname.startsWith("/s/")) {
const id = url.pathname.split("/s/")[1];
if (!id || !env.SUBS) {
return new Response("Subscription Not Found or KV Not Bound", { status: 404, headers: corsHeaders });
}
const yamlContent = await env.SUBS.get(id);
if (!yamlContent) {
return new Response("Subscription expired or does not exist", { status: 404, headers: corsHeaders });
}
// 异步滑动续期 7 天
ctx.waitUntil(
env.SUBS.put(id, yamlContent, { expirationTtl: 86400 * 7 })
);
return new Response(yamlContent, {
status: 200,
headers: {
...corsHeaders,
"Content-Type": "text/yaml; charset=utf-8",
"Profile-Update-Interval": "24",
"Content-Disposition": `inline; filename="config_${id.slice(0, 8)}.yaml"`
}
});
}
// 2. 上传配置生成托管链接
if (request.method === "POST" && url.pathname === "/upload") {
try {
const yamlContent = await request.text();
if (!yamlContent || yamlContent.length < 10) {
return new Response(JSON.stringify({ success: false, error: "内容为空" }), { status: 400, headers: { ...corsHeaders, "Content-Type": "application/json" } });
}
if (yamlContent.length > 100 * 1024) {
return new Response(JSON.stringify({ success: false, error: "配置超过 100KB" }), { status: 400, headers: { ...corsHeaders, "Content-Type": "application/json" } });
}
if (!env.SUBS) {
return new Response(JSON.stringify({ success: false, error: "未绑定 SUBS KV 命名空间" }), { status: 500, headers: { ...corsHeaders, "Content-Type": "application/json" } });
}
const array = new Uint8Array(16);
crypto.getRandomValues(array);
const id = Array.from(array, byte => byte.toString(16).padStart(2, '0')).join('');
await env.SUBS.put(id, yamlContent, { expirationTtl: 86400 * 7 });
const subUrl = `${url.origin}/s/${id}`;
return new Response(JSON.stringify({ success: true, url: subUrl }), {
status: 200,
headers: { ...corsHeaders, "Content-Type": "application/json" }
});
} catch (e) {
return new Response(JSON.stringify({ success: false, error: e.message }), { status: 500, headers: { ...corsHeaders, "Content-Type": "application/json" } });
}
}
// 3. 跨域代理拉取
const targetUrl = url.searchParams.get("url");
const userAgent = url.searchParams.get("ua") || "ClashMeta/1.18.0 Mihomo";
if (!targetUrl) {
return new Response("Mihomo 2YAML Worker Service Active", { status: 200, headers: corsHeaders });
}
try {
const response = await fetch(targetUrl, { headers: { "User-Agent": userAgent } });
const resHeaders = new Headers(response.headers);
resHeaders.set("Access-Control-Allow-Origin", "*");
resHeaders.set("Access-Control-Allow-Methods", "GET, OPTIONS");
return new Response(response.body, { status: response.status, headers: resHeaders });
} catch (e) {
return new Response(`Fetch Error: ${e.message}`, { status: 500, headers: corsHeaders });
}
}
};