-
Notifications
You must be signed in to change notification settings - Fork 0
feat: add AliDNS and Cloudflare DNS resolvers with corresponding tests #2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
94ceabd
02c4ae1
67ee6a6
8cba2d9
0ab6226
ae5176e
351544b
9885826
d2eb43c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,15 @@ | ||||||||||||||||||||
| import type { CustomDnsResolver, IDNSQueryResponse } from "../.."; | ||||||||||||||||||||
|
|
||||||||||||||||||||
| export const aliDnsResolver: CustomDnsResolver = async (domain) => { | ||||||||||||||||||||
| const url = new URL("https://dns.alidns.com/resolve"); | ||||||||||||||||||||
| url.searchParams.set("name", domain); | ||||||||||||||||||||
| url.searchParams.set("type", "16"); | ||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can maybe extract that 16 number to a variable with a clear name on what that is? :)
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||||||||||||||||||||
|
|
||||||||||||||||||||
| const res = await fetch(url, { method: "GET" }); | ||||||||||||||||||||
|
|
||||||||||||||||||||
| if (!res.ok) { | ||||||||||||||||||||
| throw new Error(`Ali DNS request failed: HTTP ${res.status}`); | ||||||||||||||||||||
| } | ||||||||||||||||||||
|
|
||||||||||||||||||||
| return res.json() as Promise<IDNSQueryResponse>; | ||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Any chance the
Suggested change
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||||||||||||||||||||
| }; | ||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| import type { CustomDnsResolver, IDNSQueryResponse } from "../.."; | ||
|
|
||
| export const cloudflareDnsResolver: CustomDnsResolver = async (domain) => { | ||
| const url = new URL("https://cloudflare-dns.com/dns-query"); | ||
| url.searchParams.set("name", domain); | ||
| url.searchParams.set("type", "TXT"); | ||
|
|
||
| const res = await fetch(url, { | ||
| method: "GET", | ||
| headers: { Accept: "application/dns-json" }, | ||
| }); | ||
|
|
||
| if (!res.ok) { | ||
| throw new Error(`Cloudflare DNS request failed: HTTP ${res.status}`); | ||
| } | ||
|
|
||
| return res.json() as Promise<IDNSQueryResponse>; | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,112 @@ | ||
| import { setupServer, SetupServerApi } from "msw/node"; | ||
| import { http, HttpResponse } from "msw"; | ||
| import { aliDnsResolver } from "./ali-dns-resolver"; | ||
| import { cloudflareDnsResolver } from "./cloudflare-dns-resolver"; | ||
| import { googleDnsResolver } from "./google-dns-resolver"; | ||
|
|
||
| const emptyDnsJson = { | ||
| Status: 0, | ||
| TC: false, | ||
| RD: true, | ||
| RA: true, | ||
| AD: false, | ||
| CD: false, | ||
| Answer: [] as [], | ||
| }; | ||
|
|
||
| describe("googleDnsResolver", () => { | ||
| let server: SetupServerApi; | ||
|
|
||
| afterEach(() => { | ||
| server.close(); | ||
| }); | ||
|
|
||
| test("requests Google DNS JSON with name, TXT type, and encoded query", async () => { | ||
| server = setupServer( | ||
| http.get("https://dns.google/resolve", ({ request }) => { | ||
| const url = new URL(request.url); | ||
| expect(url.searchParams.get("name")).toBe("my domain.test"); | ||
| expect(url.searchParams.get("type")).toBe("TXT"); | ||
| return HttpResponse.json(emptyDnsJson); | ||
| }) | ||
| ); | ||
| server.listen(); | ||
|
|
||
| const out = await googleDnsResolver("my domain.test"); | ||
| expect(out).toMatchObject({ Status: 0, Answer: [] }); | ||
| }); | ||
|
|
||
| test("throws when Google DNS returns non-2xx", async () => { | ||
| server = setupServer( | ||
| http.get("https://dns.google/resolve", () => new HttpResponse(null, { status: 503 })) | ||
| ); | ||
| server.listen(); | ||
|
|
||
| await expect(googleDnsResolver("my.domain.test")).rejects.toThrow(/HTTP 503/); | ||
| }); | ||
| }); | ||
|
|
||
| describe("cloudflareDnsResolver", () => { | ||
| let server: SetupServerApi; | ||
|
|
||
| afterEach(() => { | ||
| server.close(); | ||
| }); | ||
|
|
||
| test("requests Cloudflare DNS JSON with name, TXT type, Accept header, and encoded query", async () => { | ||
| server = setupServer( | ||
| http.get("https://cloudflare-dns.com/dns-query", ({ request }) => { | ||
| const url = new URL(request.url); | ||
| expect(url.searchParams.get("name")).toBe("cf example.test"); | ||
| expect(url.searchParams.get("type")).toBe("TXT"); | ||
| expect(request.headers.get("accept")).toBe("application/dns-json"); | ||
| return HttpResponse.json(emptyDnsJson); | ||
| }) | ||
| ); | ||
| server.listen(); | ||
|
|
||
| const out = await cloudflareDnsResolver("cf example.test"); | ||
| expect(out).toMatchObject({ Status: 0, Answer: [] }); | ||
| }); | ||
|
|
||
| test("throws when Cloudflare DNS returns non-2xx", async () => { | ||
| server = setupServer( | ||
| http.get("https://cloudflare-dns.com/dns-query", () => new HttpResponse(null, { status: 502 })) | ||
| ); | ||
| server.listen(); | ||
|
|
||
| await expect(cloudflareDnsResolver("cf.example.test")).rejects.toThrow(/HTTP 502/); | ||
| }); | ||
| }); | ||
|
|
||
| describe("aliDnsResolver", () => { | ||
| let server: SetupServerApi; | ||
|
|
||
| afterEach(() => { | ||
| server.close(); | ||
| }); | ||
|
|
||
| test("requests Ali DNS JSON with name, type 16 (TXT), and encoded query", async () => { | ||
| server = setupServer( | ||
| http.get("https://dns.alidns.com/resolve", ({ request }) => { | ||
| const url = new URL(request.url); | ||
| expect(url.searchParams.get("name")).toBe("ali example.test"); | ||
| expect(url.searchParams.get("type")).toBe("16"); | ||
| return HttpResponse.json(emptyDnsJson); | ||
| }) | ||
| ); | ||
| server.listen(); | ||
|
|
||
| const out = await aliDnsResolver("ali example.test"); | ||
| expect(out).toMatchObject({ Status: 0, Answer: [] }); | ||
| }); | ||
|
|
||
| test("throws when Ali DNS returns non-2xx", async () => { | ||
| server = setupServer( | ||
| http.get("https://dns.alidns.com/resolve", () => new HttpResponse(null, { status: 503 })) | ||
| ); | ||
| server.listen(); | ||
|
|
||
| await expect(aliDnsResolver("ali.example.test")).rejects.toThrow(/HTTP 503/); | ||
| }); | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| import type { CustomDnsResolver, IDNSQueryResponse } from "../.."; | ||
|
|
||
| export const googleDnsResolver: CustomDnsResolver = async (domain) => { | ||
| const url = new URL("https://dns.google/resolve"); | ||
| url.searchParams.set("name", domain); | ||
| url.searchParams.set("type", "TXT"); | ||
|
|
||
| const res = await fetch(url, { method: "GET" }); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. method GET is the default. You can remove it :)
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
|
||
| if (!res.ok) { | ||
| throw new Error(`Google DNS request failed: HTTP ${res.status}`); | ||
| } | ||
|
|
||
| return res.json() as Promise<IDNSQueryResponse>; | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| export * from "./google-dns-resolver"; | ||
| export * from "./cloudflare-dns-resolver"; | ||
| export * from "./ali-dns-resolver"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can prolly add in a check on Domain existence just in case anyone passes empty string
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
67ee6a6