Skip to content

Commit

Permalink
Add first version of Global DNS 🌍
Browse files Browse the repository at this point in the history
  • Loading branch information
wotschofsky committed Jan 6, 2024
1 parent 7f62cf1 commit 54f0ef9
Show file tree
Hide file tree
Showing 25 changed files with 598 additions and 11 deletions.
62 changes: 62 additions & 0 deletions app/lookup/[domain]/map/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import type { FC } from 'react';

import ResultsGlobe from '@/components/ResultsGlobe';

export const runtime = 'edge';

const regions: Record<string, { name: string; lat: number; lng: number }> = {
arn1: { lat: 59.652222, lng: 17.918611, name: 'Stockholm, Sweden' },
bom1: { lat: 19.088744, lng: 72.867905, name: 'Mumbai, India' },
cdg1: { lat: 49.009691, lng: 2.547925, name: 'Paris, France' },
cle1: { lat: 41.405772, lng: -81.849769, name: 'Cleveland, USA' },
cpt1: { lat: -33.964806, lng: 18.601667, name: 'Cape Town, South Africa' },
dub1: { lat: 53.421333, lng: -6.270075, name: 'Dublin, Ireland' },
fra1: { lat: 50.033333, lng: 8.570556, name: 'Frankfurt, Germany' },
gru1: { lat: -23.435556, lng: -46.473056, name: 'São Paulo, Brazil' },
hkg1: { lat: 22.308046, lng: 113.91848, name: 'Hong Kong, China' },
hnd1: { lat: 35.553333, lng: 139.781111, name: 'Tokyo, Japan' },
iad1: { lat: 38.944, lng: -77.456, name: 'Dulles, USA' },
icn1: { lat: 37.4625, lng: 126.439167, name: 'Seoul, South Korea' },
kix1: { lat: 34.434167, lng: 135.232778, name: 'Osaka, Japan' },
lhr1: { lat: 51.477, lng: -0.461, name: 'London, UK' },
pdx1: { lat: 45.5875, lng: -122.593333, name: 'Portland, USA' },
sfo1: { lat: 37.618056, lng: -122.378611, name: 'San Francisco, USA' },
sin1: { lat: 1.356944, lng: 103.988611, name: 'Singapore, Singapore' },
syd1: { lat: -33.946111, lng: 151.177222, name: 'Sydney, Australia' },
};

type MapResultsPageProps = {
params: {
domain: string;
};
};

const MapResultsPage: FC<MapResultsPageProps> = async ({
params: { domain },
}) => {
const markers = await Promise.all(
Object.entries(regions).map(async ([code, data]) => {
const response = await fetch(
`${
process.env.SITE_URL ||
process.env.VERCEL_URL ||
'http://localhost:3000'
}/lookup/${domain}/map/resolve/${code}?type=A&domain=${domain}`
);
if (!response.ok)
throw new Error(`Failed to fetch ${code}, ${await response.text()}`);
const results = await response.json();

return {
...data,
results: {
A: results as string[],
},
};
})
);

return <ResultsGlobe markers={markers} />;
};

export default MapResultsPage;
6 changes: 6 additions & 0 deletions app/lookup/[domain]/map/resolve/arn1/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { handler } from '../base';

export const runtime = 'edge';
export const preferredRegion = 'arn1';

export const GET = handler;
30 changes: 30 additions & 0 deletions app/lookup/[domain]/map/resolve/base.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
export const handler = async (request: Request) => {
const { searchParams } = new URL(request.url);
const type = searchParams.get('type');
const domain = searchParams.get('domain');

if (!type || !domain) {
return Response.json(
{
error: true,
message: '"type" and "domain" params are required',
},
{
status: 400,
headers: {
'Content-Type': 'application/json',
},
}
);
}

const response = await fetch(
`https://cloudflare-dns.com/dns-query?name=${domain}&type=${type}`,
{
headers: { Accept: 'application/dns-json' },
}
);
const results = await response.json();

return Response.json(results.Answer.map((a: { data: string }) => a.data));
};
6 changes: 6 additions & 0 deletions app/lookup/[domain]/map/resolve/bom1/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { handler } from '../base';

export const runtime = 'edge';
export const preferredRegion = 'bom1';

export const GET = handler;
6 changes: 6 additions & 0 deletions app/lookup/[domain]/map/resolve/cdg1/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { handler } from '../base';

export const runtime = 'edge';
export const preferredRegion = 'cdg1';

export const GET = handler;
6 changes: 6 additions & 0 deletions app/lookup/[domain]/map/resolve/cle1/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { handler } from '../base';

export const runtime = 'edge';
export const preferredRegion = 'cle1';

export const GET = handler;
6 changes: 6 additions & 0 deletions app/lookup/[domain]/map/resolve/cpt1/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { handler } from '../base';

export const runtime = 'edge';
export const preferredRegion = 'cpt1';

export const GET = handler;
6 changes: 6 additions & 0 deletions app/lookup/[domain]/map/resolve/dub1/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { handler } from '../base';

export const runtime = 'edge';
export const preferredRegion = 'dub1';

export const GET = handler;
6 changes: 6 additions & 0 deletions app/lookup/[domain]/map/resolve/fra1/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { handler } from '../base';

export const runtime = 'edge';
export const preferredRegion = 'fra1';

export const GET = handler;
6 changes: 6 additions & 0 deletions app/lookup/[domain]/map/resolve/gru1/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { handler } from '../base';

export const runtime = 'edge';
export const preferredRegion = 'gru1';

export const GET = handler;
6 changes: 6 additions & 0 deletions app/lookup/[domain]/map/resolve/hkg1/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { handler } from '../base';

export const runtime = 'edge';
export const preferredRegion = 'hkg1';

export const GET = handler;
6 changes: 6 additions & 0 deletions app/lookup/[domain]/map/resolve/hnd1/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { handler } from '../base';

export const runtime = 'edge';
export const preferredRegion = 'hnd1';

export const GET = handler;
6 changes: 6 additions & 0 deletions app/lookup/[domain]/map/resolve/iad1/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { handler } from '../base';

export const runtime = 'edge';
export const preferredRegion = 'iad1';

export const GET = handler;
6 changes: 6 additions & 0 deletions app/lookup/[domain]/map/resolve/icn1/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { handler } from '../base';

export const runtime = 'edge';
export const preferredRegion = 'icn1';

export const GET = handler;
6 changes: 6 additions & 0 deletions app/lookup/[domain]/map/resolve/kix1/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { handler } from '../base';

export const runtime = 'edge';
export const preferredRegion = 'kix1';

export const GET = handler;
6 changes: 6 additions & 0 deletions app/lookup/[domain]/map/resolve/lhr1/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { handler } from '../base';

export const runtime = 'edge';
export const preferredRegion = 'lhr1';

export const GET = handler;
6 changes: 6 additions & 0 deletions app/lookup/[domain]/map/resolve/pdx1/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { handler } from '../base';

export const runtime = 'edge';
export const preferredRegion = 'pdx1';

export const GET = handler;
6 changes: 6 additions & 0 deletions app/lookup/[domain]/map/resolve/sfo1/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { handler } from '../base';

export const runtime = 'edge';
export const preferredRegion = 'sfo1';

export const GET = handler;
6 changes: 6 additions & 0 deletions app/lookup/[domain]/map/resolve/sin1/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { handler } from '../base';

export const runtime = 'edge';
export const preferredRegion = 'sin1';

export const GET = handler;
6 changes: 6 additions & 0 deletions app/lookup/[domain]/map/resolve/syd1/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { handler } from '../base';

export const runtime = 'edge';
export const preferredRegion = 'syd1';

export const GET = handler;
39 changes: 39 additions & 0 deletions components/ResultsGlobe.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
'use client';

import type { FC } from 'react';
import Globe from 'react-globe.gl';

export const runtime = 'edge';

type ResultsGlobeProps = {
markers: {
name: string;
lat: number;
lng: number;
results: {
A: string[];
};
}[];
};

const ResultsGlobe: FC<ResultsGlobeProps> = ({ markers }) => (
<Globe
// Map from https://github.com/vasturiano/three-globe/blob/7717c8e54c98dcb3e92df5a95923f51387a496a1/example/img/earth-day.jpg
globeImageUrl="/assets/earth-day.jpg"
backgroundColor="rgba(0,0,0,0)"
htmlElementsData={markers}
// @ts-expect-error
htmlElement={(d: ResultsGlobeProps['markers'][number]) => {
const el = document.createElement('div');
el.innerHTML = `<div class="relative bg-white p-2 rounded-lg shadow-md">
<h3 class="text-sm font-bold mb-2">${d.name}</h3>
${d.results.A.map(
(ip) => `<p class="text-xs text-gray-500">${ip}</p>`
).join('')}
</div>`;
return el;
}}
/>
);

export default ResultsGlobe;
46 changes: 37 additions & 9 deletions components/ResultsTabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@ const ResultsTabs: FC<ResultsTabsProps> = ({ domain }) => {
const selectedSegment = useSelectedLayoutSegment();

useHotkeys('alt+1', () => router.push(`/lookup/${domain}`), [router]);
useHotkeys('alt+2', () => router.push(`/lookup/${domain}/whois`), [router]);
useHotkeys('alt+3', () => router.push(`/lookup/${domain}/certs`), [router]);
useHotkeys('alt+2', () => router.push(`/lookup/${domain}/map`), [router]);
useHotkeys('alt+3', () => router.push(`/lookup/${domain}/whois`), [router]);
useHotkeys('alt+4', () => router.push(`/lookup/${domain}/certs`), [router]);

return (
<div className="group mb-6 mt-6 border-b border-gray-200 text-center text-sm font-medium text-gray-500 dark:border-gray-700 dark:text-gray-400">
Expand All @@ -37,7 +38,7 @@ const ResultsTabs: FC<ResultsTabsProps> = ({ domain }) => {
}
>
DNS
<span className="pointer-events-none absolute bottom-0 block translate-y-4 text-xs text-muted-foreground opacity-0 transition-all group-hover:translate-y-6 group-hover:opacity-100">
<span className="pointer-events-none absolute bottom-0 left-1/2 block w-full -translate-x-1/2 translate-y-4 text-xs text-muted-foreground opacity-0 transition-all group-hover:translate-y-6 group-hover:opacity-100">
{isAppleDevice() ? (
<>
<OptionIcon
Expand All @@ -52,6 +53,32 @@ const ResultsTabs: FC<ResultsTabsProps> = ({ domain }) => {
</span>
</Link>
</li>
<li className="mr-2">
<Link
href={`/lookup/${domain}/map`}
className={
selectedSegment === 'map'
? 'relative inline-block rounded-t-lg border-b-2 border-primary p-4 text-primary'
: 'relative inline-block rounded-t-lg border-b-2 border-transparent p-4 hover:border-gray-300 hover:text-gray-600 dark:hover:text-gray-300'
}
aria-current="page"
>
Global DNS
<span className="pointer-events-none absolute bottom-0 left-1/2 block w-full -translate-x-1/2 translate-y-4 text-xs text-muted-foreground opacity-0 transition-all group-hover:translate-y-6 group-hover:opacity-100">
{isAppleDevice() ? (
<>
<OptionIcon
className="inline-block h-3 w-3"
strokeWidth={3}
/>
{' + 2'}
</>
) : (
'alt+2'
)}
</span>
</Link>
</li>
<li className="mr-2">
<Link
href={`/lookup/${domain}/whois`}
Expand All @@ -63,21 +90,22 @@ const ResultsTabs: FC<ResultsTabsProps> = ({ domain }) => {
aria-current="page"
>
Whois
<span className="pointer-events-none absolute bottom-0 block translate-y-4 text-xs text-muted-foreground opacity-0 transition-all group-hover:translate-y-6 group-hover:opacity-100">
<span className="pointer-events-none absolute bottom-0 left-1/2 block w-full -translate-x-1/2 translate-y-4 text-xs text-muted-foreground opacity-0 transition-all group-hover:translate-y-6 group-hover:opacity-100">
{isAppleDevice() ? (
<>
<OptionIcon
className="inline-block h-3 w-3"
strokeWidth={3}
/>
{' + 2'}
{' + 3'}
</>
) : (
'alt+2'
'alt+3'
)}
</span>
</Link>
</li>

<li className="mr-2">
<Link
href={`/lookup/${domain}/certs`}
Expand All @@ -89,17 +117,17 @@ const ResultsTabs: FC<ResultsTabsProps> = ({ domain }) => {
aria-current="page"
>
Certs
<span className="pointer-events-none absolute bottom-0 block translate-y-4 text-xs text-muted-foreground opacity-0 transition-all group-hover:translate-y-6 group-hover:opacity-100">
<span className="pointer-events-none absolute bottom-0 left-1/2 block w-full -translate-x-1/2 translate-y-4 text-xs text-muted-foreground opacity-0 transition-all group-hover:translate-y-6 group-hover:opacity-100">
{isAppleDevice() ? (
<>
<OptionIcon
className="inline-block h-3 w-3"
strokeWidth={3}
/>
{' + 3'}
{' + 4'}
</>
) : (
'alt+3'
'alt+4'
)}
</span>
</Link>
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
"punycode": "^2.3.1",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-globe.gl": "^2.27.1",
"react-hotkeys-hook": "^4.4.1",
"react-icons": "^4.12.0",
"react-leaflet": "^4.2.1",
Expand Down
Loading

0 comments on commit 54f0ef9

Please sign in to comment.