(name, type, endpoint = 'https://cloudflare-dns.com/dns-query')
| 247 | } |
| 248 | |
| 249 | async function dohQuery(name, type, endpoint = 'https://cloudflare-dns.com/dns-query') { |
| 250 | const startedAt = performance.now(); |
| 251 | |
| 252 | try { |
| 253 | const response = await fetch( |
| 254 | `${endpoint}?name=${encodeURIComponent(name)}&type=${encodeURIComponent(type)}`, |
| 255 | { |
| 256 | headers: { |
| 257 | accept: 'application/dns-json' |
| 258 | } |
| 259 | } |
| 260 | ); |
| 261 | |
| 262 | if (!response.ok) { |
| 263 | console.warn(`[DoH] ${name} ${type} failed with status ${response.status}`); |
| 264 | return []; |
| 265 | } |
| 266 | |
| 267 | const payload = await response.json(); |
| 268 | if (!Array.isArray(payload.Answer)) { |
| 269 | console.log(`[DoH] ${name} ${type} returned 0 answers in ${(performance.now() - startedAt).toFixed(2)}ms`); |
| 270 | return []; |
| 271 | } |
| 272 | |
| 273 | const answers = payload.Answer.map(answer => ({ |
| 274 | name: answer.name || name, |
| 275 | type: answer.type, |
| 276 | TTL: answer.TTL, |
| 277 | data: answer.type === 16 ? normalizeTxtValue(answer.data) : answer.data |
| 278 | })); |
| 279 | |
| 280 | console.log(`[DoH] ${name} ${type} returned ${answers.length} answers in ${(performance.now() - startedAt).toFixed(2)}ms`); |
| 281 | return answers; |
| 282 | } catch (error) { |
| 283 | console.error(`[DoH] ${name} ${type} error after ${(performance.now() - startedAt).toFixed(2)}ms`, error); |
| 284 | return []; |
| 285 | } |
| 286 | } |
| 287 | |
| 288 | function generateHTML(备案内容) { |
| 289 | return `<!DOCTYPE html> |
no test coverage detected