docs: ip lookup

This commit is contained in:
Carl-Gerhard Lindesvärd
2025-12-16 20:31:44 +01:00
parent 3158ebfbda
commit 1e4f02fb5e
2 changed files with 7 additions and 127 deletions

View File

@@ -27,10 +27,6 @@ interface IPInfoResponse {
latitude: number | undefined;
longitude: number | undefined;
};
isp: string | null;
asn: string | null;
organization: string | null;
hostname: string | null;
isLocalhost: boolean;
isPrivate: boolean;
}
@@ -90,84 +86,6 @@ function isPrivateIP(ip: string): boolean {
return false;
}
async function getIPInfo(ip: string): Promise<IPInfo> {
if (!ip || ip === '127.0.0.1' || ip === '::1') {
return {
ip,
location: {
country: undefined,
city: undefined,
region: undefined,
latitude: undefined,
longitude: undefined,
},
isp: null,
asn: null,
organization: null,
hostname: null,
};
}
// Get geolocation
const geo = await getGeoLocation(ip);
// Get ISP/ASN info
let isp: string | null = null;
let asn: string | null = null;
let organization: string | null = null;
if (!isPrivateIP(ip)) {
try {
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), 3000);
const response = await fetch(
`https://ip-api.com/json/${ip}?fields=isp,as,org,query,reverse`,
{
signal: controller.signal,
},
);
clearTimeout(timeout);
if (response.ok) {
const data = await response.json();
if (data.status !== 'fail') {
isp = data.isp || null;
asn = data.as ? `AS${data.as.split(' ')[0]}` : null;
organization = data.org || null;
}
}
} catch {
// Ignore errors
}
}
// Reverse DNS lookup for hostname
let hostname: string | null = null;
try {
const hostnames = await dns.reverse(ip);
hostname = hostnames[0] || null;
} catch {
// Ignore errors
}
return {
ip,
location: {
country: geo.country,
city: geo.city,
region: geo.region,
latitude: geo.latitude,
longitude: geo.longitude,
},
isp,
asn,
organization,
hostname,
};
}
export async function GET(request: Request) {
const { searchParams } = new URL(request.url);
const ipParam = searchParams.get('ip');
@@ -209,12 +127,17 @@ export async function GET(request: Request) {
}
try {
const info = await getIPInfo(ipToLookup);
const geo = await fetch('https://api.openpanel.dev/misc/geo', {
headers: request.headers,
})
.then((res) => res.json())
.then((data) => data.selected.geo);
const isLocalhost = ipToLookup === '127.0.0.1' || ipToLookup === '::1';
const isPrivate = isPrivateIP(ipToLookup);
const response: IPInfoResponse = {
...info,
location: geo,
ip: ipToLookup,
isLocalhost,
isPrivate,
};

View File

@@ -275,49 +275,6 @@ export default function IPLookupPage() {
</div>
)}
{/* Network Information */}
{(result.isp ||
result.asn ||
result.organization ||
result.hostname) && (
<div>
<h3 className="text-lg font-semibold mb-4 flex items-center gap-2">
<Network className="size-5" />
Network Information
</h3>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
{result.isp && (
<InfoCard
icon={<Building2 className="size-5" />}
label="ISP"
value={result.isp}
/>
)}
{result.asn && (
<InfoCard
icon={<Network className="size-5" />}
label="ASN"
value={result.asn}
/>
)}
{result.organization && (
<InfoCard
icon={<Building2 className="size-5" />}
label="Organization"
value={result.organization}
/>
)}
{result.hostname && (
<InfoCard
icon={<Server className="size-5" />}
label="Hostname"
value={result.hostname}
/>
)}
</div>
</div>
)}
{/* Map Preview */}
{result.location.latitude && result.location.longitude && (
<div>