proxy.ts : le nouveau middleware de Next.js 16
Dans Next.js 16, middleware.ts est déprécié et remplacé par proxy.ts. Le changement de nom clarifie le rôle de ce fichier : il intercepte les requêtes réseau avant qu’elles atteignent vos pages ou API. Même logique, nom plus explicite, runtime Node.js par défaut.
Next.js 15 — middleware.ts (déprécié)
// middleware.ts
export default function middleware(req) {
// ...
}
export const config = { matcher: ['/dashboard/:path*'] };Next.js 16 — proxy.ts
// proxy.ts — même logique, nouveau nom
export default function proxy(req) {
// ...
}
export const config = { matcher: ['/dashboard/:path*'] };
Migration automatique disponible
Si vous avez un projet existant avec middleware.ts, renommez simplement le fichier en proxy.ts et la fonction exportée en proxy. Le codemod officiel (npx @next/codemod upgrade latest) s’en charge automatiquement.
Structure de base de proxy.ts
TypeScript
proxy.ts — racine du projet
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
export default function proxy(request: NextRequest) {
// Lire l'URL courante
const { pathname } = request.nextUrl;
// Laisser passer sans modification
return NextResponse.next();
}
// Définir sur quelles routes proxy.ts s'exécute
export const config = {
matcher: [
'/((?!_next/static|_next/image|favicon.ico).*)',
],
};
Cas d’usage 1 : protection de routes (auth)
TypeScript
proxy.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
export default function proxy(request: NextRequest) {
const { pathname } = request.nextUrl;
// Lire le token depuis les cookies
const token = request.cookies.get('auth-token')?.value;
// Routes protégées : /dashboard et ses sous-pages
if (pathname.startsWith('/dashboard') && !token) {
const loginUrl = new URL('/login', request.url);
loginUrl.searchParams.set('from', pathname); // URL de retour
return NextResponse.redirect(loginUrl);
}
// Déjà connecté → ne pas afficher /login ni /register
if (['/login', '/register'].includes(pathname) && token) {
return NextResponse.redirect(new URL('/dashboard', request.url));
}
return NextResponse.next();
}
export const config = {
matcher: ['/dashboard/:path*', '/login', '/register'],
};
Cas d’usage 2 : redirections et réécriture d’URL
TypeScript
proxy.ts
export default function proxy(request: NextRequest) {
const { pathname } = request.nextUrl;
// Redirection permanente (301)
if (pathname === '/old-blog') {
return NextResponse.redirect(
new URL('/blog', request.url),
{ status: 301 }
);
}
// Réécriture d'URL (l'URL dans le navigateur ne change pas)
if (pathname.startsWith('/api/v1')) {
const rewriteUrl = new URL(
pathname.replace('/api/v1', '/api/v2'),
request.url
);
return NextResponse.rewrite(rewriteUrl);
}
return NextResponse.next();
}
Cas d’usage 3 : headers et internationalisation
TypeScript
proxy.ts
export default function proxy(request: NextRequest) {
// Ajouter un header custom à toutes les réponses
const response = NextResponse.next();
response.headers.set('x-app-version', '16.0');
// Détecter la langue et rediriger
const { pathname } = request.nextUrl;
const locale = request.cookies.get('locale')?.value ?? 'fr';
if (!pathname.startsWith(`/${locale}`)) {
return NextResponse.redirect(
new URL(`/${locale}${pathname}`, request.url)
);
}
return response;
}
proxy.ts s’exécute sur chaque requête
Gardez le code de proxy.ts minimal et rapide. Pas de lecture en base de données, pas d’appels API lourds. Pour valider un JWT, vérifiez uniquement la signature côté proxy — ne récupérez pas les données utilisateur complètes depuis la DB ici.
Exercice pratique
- Créez un fichier
proxy.tsà la racine de votre projet - Redirigez automatiquement
/adminvers/loginsi le cookieauth-tokenest absent - Ajoutez une redirection 301 de
/accueilvers/ - Testez en ajoutant/supprimant manuellement le cookie dans les DevTools du navigateur
- Vérifiez dans le terminal Next.js que le proxy s’exécute à chaque requête sur les routes matchées