Files
2025-11-15 19:21:25 +07:00

131 lines
4.3 KiB
JavaScript

async function handleRequest(request) {
const originalUrl = new URL(request.url);
const baseUrlParam = originalUrl.searchParams.get("url");
let targetUrl;
if (baseUrlParam) {
targetUrl = new URL(baseUrlParam);
for (const [key, value] of originalUrl.searchParams.entries()) {
if (key !== "url") {
targetUrl.searchParams.append(key, value);
}
}
if (new URL(baseUrlParam).pathname === "/" || new URL(baseUrlParam).pathname === "") {
targetUrl.pathname = originalUrl.pathname;
}
} else {
const referer = request.headers.get("referer");
if (!referer) {
return new Response("Missing `url` parameter and referer", { status: 400 });
}
const refUrl = new URL(referer);
const refBase = refUrl.searchParams.get("url");
if (!refBase) {
return new Response("Missing base `url` in referer", { status: 400 });
}
targetUrl = new URL(refBase);
if (new URL(refBase).pathname === "/" || new URL(refBase).pathname === "") {
targetUrl.pathname = originalUrl.pathname;
}
targetUrl.search = originalUrl.search;
}
try {
const method = request.method;
const headers = new Headers(request.headers);
headers.delete("Cf-Connecting-Ip");
headers.delete("x-forwarded-for");
headers.delete("x-real-ip");
headers.delete("forwarded");
headers.delete("cdn-loop");
const contentType = headers.get("Content-Type");
if (contentType && contentType.startsWith("application/json") && !contentType.includes("charset")) {
headers.set("Content-Type", "application/json; charset=UTF-8");
}
const init = {
method,
headers,
redirect: "follow",
};
if (method !== "GET" && method !== "HEAD") {
init.body = request.body;
}
const proxyReq = new Request(targetUrl.toString(), init);
const proxiedRes = await fetch(proxyReq);
const resContentType = proxiedRes.headers.get("Content-Type") || "";
// Nếu là HTML, xử lý lại nội dung để rewrite URL
if (resContentType.includes("text/html")) {
let html = await proxiedRes.text();
const baseProxy = `https://cloudflare-proxy.miti99.workers.dev/?url=`;
// Chuyển các href/src/action thành proxy link
html = html.replace(
/(?:href|src|action)=["']([^"']+)["']/gi,
(match, p1) => {
if (p1.startsWith("javascript:") || p1.startsWith("#")) return match;
const newUrl = new URL(p1, targetUrl).toString();
return match.replace(p1, `${baseProxy}${encodeURIComponent(newUrl)}`);
}
);
const response = new Response(html, {
status: proxiedRes.status,
headers: {
"Content-Type": "text/html; charset=UTF-8",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS, HEAD",
"Access-Control-Allow-Headers": request.headers.get("Access-Control-Request-Headers") || "Content-Type",
"Cache-Control": "no-store",
},
});
return response;
}
// Nếu không phải HTML, trả lại nguyên văn
const res = new Response(proxiedRes.body, proxiedRes);
const reqAllowHeaders = request.headers.get("Access-Control-Request-Headers");
const allowHeaders = reqAllowHeaders ? reqAllowHeaders : "Content-Type";
res.headers.set("Access-Control-Allow-Origin", "*");
res.headers.set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD");
res.headers.set("Access-Control-Allow-Headers", allowHeaders);
res.headers.set("Cache-Control", "no-store");
return res;
} catch (err) {
return new Response(`Proxy error: ${err.message}`, { status: 500 });
}
}
function handleOptions(request) {
const reqAllowHeaders = request.headers.get("Access-Control-Request-Headers");
const allowHeaders = reqAllowHeaders ? reqAllowHeaders : "Content-Type";
const headers = {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS, HEAD",
"Access-Control-Allow-Headers": allowHeaders,
"Access-Control-Max-Age": "86400",
};
return new Response(null, { status: 204, headers });
}
addEventListener("fetch", event => {
if (event.request.method === "OPTIONS") {
event.respondWith(handleOptions(event.request));
} else {
event.respondWith(handleRequest(event.request));
}
});