Skip to content

Commit

Permalink
Move ip details lookup to edge 🌍
Browse files Browse the repository at this point in the history
  • Loading branch information
wotschofsky committed Dec 29, 2023
1 parent c87202a commit 30ce404
Showing 1 changed file with 64 additions and 12 deletions.
76 changes: 64 additions & 12 deletions app/api/lookupIp/route.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import dns from 'dns';
import { promisify } from 'util';
import isIP from 'validator/lib/isIP';

export const runtime = 'edge';

export type IpLookupResponse = {
city: string;
country: string;
Expand All @@ -16,6 +16,64 @@ export type IpLookupResponse = {

export type IpLookupErrorResponse = { error: true; message: string };

const getIpDetails = async (ip: string) => {
const response = await fetch(`http://ip-api.com/json/${ip}`);

if (!response.ok)
throw new Error(`Error fetching IP details: ${response.statusText}`);

const data = (await response.json()) as Record<string, any>;
delete data.status;

return data;
};

const ipv4ToDnsName = (ipv4: string) =>
ipv4.split('.').reverse().join('.') + '.in-addr.arpa';

const ipv6ToDnsName = (ipv6: string) => {
const segments = ipv6.split(':');
const missingSegments = 8 - segments.length + (ipv6.includes('::') ? 1 : 0);
const expandedSegments = segments.map((segment) => segment.padStart(4, '0'));
for (let i = 0; i < missingSegments; i++) {
expandedSegments.splice(segments.indexOf(''), 0, '0000');
}
const fullAddress = expandedSegments.join('');

return (
fullAddress
.split('')
.reverse()
.join('.')
.replace(/:/g, '')
.split('.')
.filter((x) => x)
.join('.') + '.ip6.arpa'
);
};

const lookupReverse = async (ip: string): Promise<string[]> => {
const reverseDnsName = ip.includes(':')
? ipv6ToDnsName(ip)
: ipv4ToDnsName(ip);

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

if (!response.ok)
throw new Error(`Error fetching DNS records: ${response.statusText}`);

const data = await response.json();

return data.Answer
? data.Answer.map((record: { data: string }) => record.data)
: [];
};

export async function GET(request: Request) {
const { searchParams } = new URL(request.url);
const ip = searchParams.get('ip');
Expand All @@ -35,16 +93,10 @@ export async function GET(request: Request) {
);
}

const url = `http://ip-api.com/json/${ip}`;
const response = await fetch(url);
const data = (await response.json()) as Record<string, any>;

let reverse: string[] = [];
try {
reverse = await promisify(dns.reverse)(ip);
} catch (error) {
console.error(error);
}
const [data, reverse] = await Promise.all([
getIpDetails(ip),
lookupReverse(ip),
]);

return new Response(
JSON.stringify({
Expand Down

1 comment on commit 30ce404

@vercel
Copy link

@vercel vercel bot commented on 30ce404 Dec 29, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.