import { NextResponse } from 'next/server'; import type { NextRequest } from 'next/server'; // Routes only accessible when not authenticated const authRoutes = ['/login', '/register']; // Routes à ne pas tracker const excludedPaths = ['/api/track', '/api/metrics', '/_next', '/favicon.ico']; export function middleware(request: NextRequest) { const { pathname } = request.nextUrl; const startTime = Date.now(); // Get token from cookies or headers const token = request.cookies.get('auth_token')?.value || request.headers.get('authorization')?.replace('Bearer ', ''); // Check if route is auth route const isAuthRoute = authRoutes.some(route => pathname.startsWith(route)); // Préparer la réponse let response: NextResponse; // If accessing auth routes with token in cookies, redirect to home if (isAuthRoute && token) { response = NextResponse.redirect(new URL('/', request.url)); } else { response = NextResponse.next(); } // Tracker les métriques HTTP (fire and forget) const shouldTrack = !excludedPaths.some(path => pathname.startsWith(path)); if (shouldTrack) { const durationMs = Date.now() - startTime; const statusCode = response.status || 200; // Envoyer les métriques de manière asynchrone (non bloquant) const trackUrl = new URL('/api/track', request.url); // Utiliser waitUntil pour ne pas bloquer la réponse // Note: waitUntil n'est pas disponible dans tous les environnements try { fetch(trackUrl.toString(), { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ method: request.method, path: pathname, statusCode, durationMs, }), }).catch(() => { // Ignorer les erreurs de tracking }); } catch { // Ignorer les erreurs de tracking } } return response; } export const config = { matcher: [ /* * Match all request paths except for the ones starting with: * - _next/static (static files) * - _next/image (image optimization files) * - favicon.ico (favicon file) * - public files (public folder) */ '/((?!_next/static|_next/image|favicon.ico|.*\\..*|public).*)', ], };