Guides d’intégration
Next.js sur Vercel
Appeler Orbit depuis une Route Handler sans exposer la clé au navigateur.
L’architecture recommandée est : navigateur → Route Handler Next.js → Orbit API.
Dans Vercel, créez uniquement des variables serveur :
ORBIT_BASE_URL
ORBIT_API_KEYNe préfixez jamais la clé avec NEXT_PUBLIC_.
// app/api/interests/search/route.ts
import { NextRequest, NextResponse } from "next/server";
const categories = new Set(["games", "movies", "anime", "series", "music", "books"]);
export async function GET(request: NextRequest) {
const query = request.nextUrl.searchParams.get("q")?.trim() ?? "";
const category = request.nextUrl.searchParams.get("category");
const limit = Number(request.nextUrl.searchParams.get("limit") ?? 20);
if (!query || query.length > 100) {
return NextResponse.json({ error: "invalid_query" }, { status: 400 });
}
if (category && !categories.has(category)) {
return NextResponse.json({ error: "invalid_category" }, { status: 400 });
}
if (!Number.isInteger(limit) || limit < 1 || limit > 50) {
return NextResponse.json({ error: "invalid_limit" }, { status: 400 });
}
const baseUrl = process.env.ORBIT_BASE_URL;
const apiKey = process.env.ORBIT_API_KEY;
if (!baseUrl || !apiKey) {
return NextResponse.json({ error: "not_configured" }, { status: 503 });
}
const orbitUrl = new URL(`${baseUrl}/v1/interests/search`);
orbitUrl.searchParams.set("q", query);
orbitUrl.searchParams.set("limit", String(limit));
if (category) orbitUrl.searchParams.set("category", category);
const response = await fetch(orbitUrl, {
headers: { Authorization: `Bearer ${apiKey}` },
cache: "no-store",
signal: AbortSignal.timeout(5_000),
});
const headers = new Headers({
"content-type": "application/json",
"cache-control": "private, no-store",
});
for (const name of [
"x-request-id",
"x-ratelimit-limit",
"x-ratelimit-remaining",
"x-ratelimit-reset",
"x-orbit-daily-ratelimit-limit",
"x-orbit-daily-ratelimit-remaining",
"x-orbit-daily-ratelimit-reset",
"retry-after",
]) {
const value = response.headers.get(name);
if (value) headers.set(name, value);
}
return new NextResponse(await response.text(), {
status: response.status,
headers,
});
}Le navigateur appelle seulement /api/interests/search. Ne lui permettez jamais de choisir l’hôte de destination et ne relayez pas son en-tête Authorization vers Orbit.
Ajoutez votre propre authentification utilisateur, validation et limitation anti-abus avant d’exposer cette route publiquement.