Geolocalizzazione IP in Next.js: schemi lato browser e lato server
Next.js può renderizzare la stessa pagina sul server o nel browser, e questa scelta determina quale endpoint di Watch-IP risolve effettivamente la posizione del visitatore — o, invece, quella del tuo server.
Prima di iniziare
- Una chiave visitatore pubblicabile per lo schema client, oppure una chiave segreta di ricerca per lo schema server — consulta l'autenticazione.
- Un progetto Next.js con App Router (gli esempi presuppongono la suddivisione tra Server e Client Component di Next.js 16).
- Per lo schema server, un header impostato dalla tua piattaforma di hosting sulle richieste in ingresso con l'IP reale del visitatore (ad esempio CF-Connecting-IP su Cloudflare) — non uno che un client potrebbe impostare da solo.
1. Capisci cosa chiama davvero ciascuno schema
GET /v1/geo identifica chiunque sia la connessione che raggiunge l'API — il browser di un visitatore che la chiama direttamente, oppure il tuo server Next.js se è il tuo codice a chiamarla durante il rendering lato server. Chiamare GET /v1/geo da un Server Component o da un Route Handler risolve la posizione di rete del tuo server, non quella del visitatore, il che di solito non è ciò che vuoi. Due schemi risolvono davvero il visitatore: eseguire la richiesta nel browser (Client Component), oppure eseguirla sul tuo server su un IP fornito con GET /v1/lookup/{ip}.
2. Client Component: chiama GET /v1/geo dal browser
È la stessa richiesta usata dalle guide JavaScript e React — un Client Component che effettua il fetch con una chiave pubblicabile. L'header Origin del browser stesso soddisfa il controllo delle origini consentite della chiave, quindi l'URL pubblico della tua app deve trovarsi in quell'elenco.
TypeScript (Client Component)
"use client";
import { useEffect, useState } from "react";
export function VisitorLocation() {
const [city, setCity] = useState<string | null>(null);
useEffect(() => {
const controller = new AbortController();
fetch("https://api.watch-ip.com/v1/geo", {
headers: { "X-Api-Key": "YOUR_PUBLISHABLE_KEY" },
signal: controller.signal,
})
.then((res) => (res.ok ? res.json() : null))
.then((geo) => setCity(geo?.city ?? null))
.catch(() => {});
return () => controller.abort();
}, []);
return <span>{city ?? "la tua zona"}</span>;
}3. Server Component o Route Handler: cerca esplicitamente l'IP del visitatore
Per risolvere la posizione di un visitatore durante il rendering lato server, non chiamare GET /v1/geo — chiama GET /v1/lookup/{ip} con una chiave segreta e l'IP reale del visitatore, letto da qualunque header la tua piattaforma di hosting imposti sulla richiesta in ingresso. Non fidarti mai di un semplice valore X-Forwarded-For che un client potrebbe impostare da solo, a meno che la tua piattaforma non lo rimuova e lo reimposti all'edge.
TypeScript (Server Component)
import { headers } from "next/headers";
export async function VisitorLocationServer() {
const ip = (await headers()).get("cf-connecting-ip");
if (!ip) return null;
const response = await fetch(`https://api.watch-ip.com/v1/lookup/${ip}`, {
headers: { Authorization: "Bearer YOUR_SECRET_KEY" },
cache: "no-store",
});
if (!response.ok) return null;
const geo = await response.json();
return <span>{geo.city ?? "la tua zona"}</span>;
}4. Non mettere in cache il risultato di un visitatore per un altro
Il cache: 'no-store' visto sopra è deliberato: il risultato di una ricerca è specifico del visitatore che l'ha richiesto. Se questo componente viene renderizzato all'interno di una rotta che Next.js o una CDN possono mettere in cache — una pagina statica, una pagina ISR, una fetch cache condivisa — una risposta memorizzata in cache mostrerebbe la città di un visitatore a chiunque arrivi dopo. Mantieni il ramo personalizzato a rendering dinamico, e non incorporare mai una risposta di ricerca in una cache a livello di pagina o di CDN.
Errori e casi limite
Un header IP mancante o vuoto (alcune configurazioni locali o con proxy non ne impostano uno) significa che non c'è alcun IP di visitatore da cercare — mostra il fallback invece di chiamare l'endpoint con una stringa vuota. Un 403 da GET /v1/lookup/{ip} di solito significa che è stata usata una chiave pubblicabile dove la rotta richiede una chiave segreta; un 400 significa che l'header conteneva qualcosa che non è un indirizzo IPv4/IPv6 valido. Consulta errori e limiti di frequenza.
Passo successivo
Per un componente riutilizzabile sia nelle app React solo client sia in Next.js, consulta la guida React — lo schema Client Component visto sopra è un wrapper specifico di Next.js attorno alla stessa richiesta.
Pagine correlate
- Geolocalizzazione del visitatoreChiama GET /v1/geo dal browser con una chiave pubblicabile.
- Riferimento GET /v1/geoRiferimento completo dei campi per l'endpoint di geolocalizzazione del visitatore.
- Riferimento GET /v1/lookup/:ipRiferimento completo dei campi per l'endpoint di ricerca di un IP arbitrario.
- Guida ReactAggiungi la posizione del visitatore a un componente React.