Initial commit: DNS Test - DNS health checking tool
Go backend (miekg/dns) + Nuxt 3 frontend (Tailwind CSS v4). 8 check categories, 52 checks total: - Overview: @ record, WWW, MX with ASN/provider lookup - Domain Registration: expiry, registrar (RDAP + whois fallback) - Parent Delegation: NS records, glue, consistency - Nameservers: 17 checks (reachability, auth, recursion, TCP/UDP, AXFR, etc.) - SOA: serial consistency, timing values - Mail (MX): 11 checks (CNAME, PTR, public IPs, consistency) - Mail Auth: SPF, DKIM, DMARC - WWW: A record, CNAME Features: - SSE streaming (results appear as each category completes) - SQLite history (modernc.org/sqlite) - Rate limiting, CORS, request logging - Dark mode, responsive design
This commit is contained in:
106
frontend/app/composables/useDnsCheck.ts
Normal file
106
frontend/app/composables/useDnsCheck.ts
Normal file
@@ -0,0 +1,106 @@
|
||||
import type { DnsReport, Category, Summary } from '~/types/dns'
|
||||
|
||||
interface StreamEvent {
|
||||
domain: string
|
||||
category: Category
|
||||
done?: boolean
|
||||
}
|
||||
|
||||
export function useDnsCheck() {
|
||||
const config = useRuntimeConfig()
|
||||
const report = ref<DnsReport | null>(null)
|
||||
const loading = ref(false)
|
||||
const error = ref<string | null>(null)
|
||||
const progress = ref(0)
|
||||
const totalCategories = 8
|
||||
|
||||
async function checkDomain(domain: string) {
|
||||
loading.value = true
|
||||
error.value = null
|
||||
report.value = null
|
||||
progress.value = 0
|
||||
|
||||
// Initialize empty report
|
||||
const startTime = Date.now()
|
||||
const partialReport: DnsReport = {
|
||||
domain,
|
||||
timestamp: new Date().toISOString(),
|
||||
duration_ms: 0,
|
||||
summary: { pass: 0, warn: 0, fail: 0, info: 0 },
|
||||
categories: [],
|
||||
}
|
||||
|
||||
try {
|
||||
const url = `${config.public.apiBase}/check/stream?domain=${encodeURIComponent(domain)}`
|
||||
const eventSource = new EventSource(url)
|
||||
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
const timeout = setTimeout(() => {
|
||||
eventSource.close()
|
||||
reject(new Error('Request timed out after 30 seconds'))
|
||||
}, 30000)
|
||||
|
||||
eventSource.onmessage = (event) => {
|
||||
try {
|
||||
const data = JSON.parse(event.data) as StreamEvent & { done?: boolean }
|
||||
|
||||
if (data.done) {
|
||||
clearTimeout(timeout)
|
||||
eventSource.close()
|
||||
partialReport.duration_ms = Date.now() - startTime
|
||||
resolve()
|
||||
return
|
||||
}
|
||||
|
||||
if (data.category) {
|
||||
partialReport.categories.push(data.category)
|
||||
progress.value = partialReport.categories.length
|
||||
|
||||
// Recalculate summary
|
||||
const summary: Summary = { pass: 0, warn: 0, fail: 0, info: 0 }
|
||||
for (const cat of partialReport.categories) {
|
||||
for (const check of cat.checks) {
|
||||
summary[check.status]++
|
||||
}
|
||||
}
|
||||
partialReport.summary = summary
|
||||
partialReport.duration_ms = Date.now() - startTime
|
||||
|
||||
// Update reactively
|
||||
report.value = { ...partialReport, categories: [...partialReport.categories] }
|
||||
}
|
||||
} catch {
|
||||
// ignore parse errors
|
||||
}
|
||||
}
|
||||
|
||||
eventSource.onerror = () => {
|
||||
clearTimeout(timeout)
|
||||
eventSource.close()
|
||||
if (partialReport.categories.length > 0) {
|
||||
// Got some results, show them
|
||||
partialReport.duration_ms = Date.now() - startTime
|
||||
report.value = { ...partialReport }
|
||||
resolve()
|
||||
} else {
|
||||
reject(new Error('Connection to DNS check server failed'))
|
||||
}
|
||||
}
|
||||
})
|
||||
} catch (e: any) {
|
||||
// Fallback to non-streaming API
|
||||
try {
|
||||
const data = await $fetch<DnsReport>(`${config.public.apiBase}/check?domain=${encodeURIComponent(domain)}`)
|
||||
report.value = data
|
||||
progress.value = totalCategories
|
||||
} catch (e2: any) {
|
||||
error.value = e2.data?.error || e2.message || e.message || 'Failed to check domain'
|
||||
}
|
||||
} finally {
|
||||
loading.value = false
|
||||
progress.value = totalCategories
|
||||
}
|
||||
}
|
||||
|
||||
return { report, loading, error, progress, totalCategories, checkDomain }
|
||||
}
|
||||
Reference in New Issue
Block a user