diff --git a/_worker.js b/_worker.js index 9ef34d7..2f356df 100644 --- a/_worker.js +++ b/_worker.js @@ -1,4 +1,4 @@ -import handler from "./common"; +import handler from "./handler/dns"; export default { fetch: async (request, env) => diff --git a/common.js b/handler/dns.js similarity index 78% rename from common.js rename to handler/dns.js index 50cca92..f87e33c 100644 --- a/common.js +++ b/handler/dns.js @@ -45,85 +45,78 @@ export default async function handler( } const { method, headers, url } = request; - const { search, searchParams, pathname } = new URL(url); + const { search, searchParams } = new URL(url); const ip = rawIP || headers.get("x-forwarded-for").split(",")[0].trim() || headers.get("x-real-ip"); - let res = new Response(null, { status: 404 }); + let res = new Response(null, { status: 400 }); // JSON API - if (pathname === "/resolve") { - res = new Response(null, { status: 400 }); - - if (method === "GET" && searchParams.has("name")) { - if (concurrent) { - res = await Promise.any( - api.map((server) => - fetch(server + search, { - method: "GET", - headers: { - "User-Agent": - "Dohna-NS (https://github.com/LittleChest/Dohna-NS)", - }, - }).then((res) => { - if (res.status !== 200) { - throw new Error( - `Failed to connect to ${server}: ${res.status} ${res.statusText}`, - ); - } - return res; - }), - ), - ); - } else { - const servers = [...api]; - while (servers.length > 0) { - const index = Math.floor(Math.random() * servers.length); - const server = servers.splice(index, 1)[0]; - try { - res = await fetch(server + search, { - method: "GET", - headers: { - "User-Agent": - "Dohna-NS (https://github.com/LittleChest/Dohna-NS)", - }, - }); - if (res.status === 200) break; - } catch (e) { - console.warn(`Failed to connect to ${server}: ${e.message}`); - continue; - } + if (method === "GET" && searchParams.has("name")) { + if (concurrent) { + res = await Promise.any( + api.map((server) => + fetch(server + search, { + method: "GET", + headers: { + "User-Agent": + "Dohna-NS (https://github.com/LittleChest/Dohna-NS)", + }, + }).then((res) => { + if (res.status !== 200) { + throw new Error( + `Failed to connect to ${server}: ${res.status} ${res.statusText}`, + ); + } + return res; + }), + ), + ); + } else { + const servers = [...api]; + while (servers.length > 0) { + const index = Math.floor(Math.random() * servers.length); + const server = servers.splice(index, 1)[0]; + try { + res = await fetch(server + search, { + method: "GET", + headers: { + "User-Agent": + "Dohna-NS (https://github.com/LittleChest/Dohna-NS)", + }, + }); + if (res.status === 200) break; + } catch (e) { + console.warn(`Failed to connect to ${server}: ${e.message}`); + continue; } - console.error("All upstream JSON API servers failed."); - res = new Response(null, { status: 500 }); } + console.error("All upstream JSON API servers failed."); + res = new Response(null, { status: 500 }); } } // DNS Query - if (pathname === "/dns-query") { - res = new Response(null, { status: 400 }); + let queryData; - let queryData; + // GET + if (method === "GET" && searchParams.has("dns")) { + // Decode the base64-encoded DNS query + try { + const decodedQuery = atob(searchParams.get("dns")); + queryData = new Uint8Array(decodedQuery.length); + for (let i = 0; i < decodedQuery.length; i++) { + queryData[i] = decodedQuery.charCodeAt(i); + } + } catch {} + } - // GET - if (method === "GET" && searchParams.has("dns")) { - // Decode the base64-encoded DNS query - try { - const decodedQuery = atob(searchParams.get("dns")); - queryData = new Uint8Array(decodedQuery.length); - for (let i = 0; i < decodedQuery.length; i++) { - queryData[i] = decodedQuery.charCodeAt(i); - } - } catch {} - } - - // POST - if (method === "POST") { - const requestBody = await request.arrayBuffer(); + // POST + if (method === "POST") { + const requestBody = await request.arrayBuffer(); // Anti-GFW if ( @@ -148,16 +141,15 @@ export default async function handler( queryData = new Uint8Array(requestBody); } - if (queryData) { - res = await queryDns( - queryData, - ip, - dns, - ipv4Prefix, - ipv6Prefix, - concurrent, - ); - } + if (queryData) { + res = await queryDns( + queryData, + ip, + dns, + ipv4Prefix, + ipv6Prefix, + concurrent, + ); } return res; diff --git a/handler/entrypoint.js b/handler/entrypoint.js new file mode 100644 index 0000000..fb81ccb --- /dev/null +++ b/handler/entrypoint.js @@ -0,0 +1,19 @@ +import dnsHandler from "./dns"; + +export default async function handler( + request, + dns, + api, + ipv4Prefix = 32, + ipv6Prefix = 128, + concurrent = false, + rawIP, + ) { + const { pathname } = new URL(request.url); + let res = new Response(null, { status: 404 }); + + // DNS over HTTPS & JSON API + if (pathname === "/dns-query" || pathname === "/resolve") { + res = dnsHandler(request, dns, api, ipv4Prefix, ipv6Prefix, concurrent, rawIP); + } +} \ No newline at end of file diff --git a/middleware.js b/middleware.js index af958ac..bbf12cf 100644 --- a/middleware.js +++ b/middleware.js @@ -1,4 +1,4 @@ -import handler from "./common"; +import handler from "./handler/dns"; export default middleware = async (request) => { return handler( diff --git a/netlify/edge-functions/middleware.js b/netlify/edge-functions/middleware.js index 3fb4ecf..5b4fb8d 100644 --- a/netlify/edge-functions/middleware.js +++ b/netlify/edge-functions/middleware.js @@ -1,4 +1,4 @@ -import handler from "../../common.js"; +import handler from "../../handler/dns.js"; export default async (request) => handler( request,