import createMiddleware from 'next-intl/middleware'; import { NextResponse } from 'next/server'; import type { NextRequest } from 'next/server'; import { getServerAppServices } from '@/lib/services/create-services.server'; // Create the internationalization middleware const intlMiddleware = createMiddleware({ // A list of all locales that are supported locales: ['en', 'de'], // Used when no locale matches defaultLocale: 'en' }); // Main middleware that logs all requests export default function middleware(request: NextRequest) { const startTime = Date.now(); const { method, url, headers } = request; const userAgent = headers.get('user-agent') || 'unknown'; const referer = headers.get('referer') || 'none'; const ip = headers.get('x-forwarded-for') || headers.get('x-real-ip') || 'unknown'; // Get logger service const services = getServerAppServices(); const logger = services.logger.child({ middleware: 'request-logger' }); // Log incoming request logger.info('Incoming request', { method, url, userAgent, referer, ip, timestamp: new Date().toISOString(), }); try { // Apply internationalization middleware const response = intlMiddleware(request); const duration = Date.now() - startTime; // Log successful response const logData: any = { method, url, status: response.status, duration, userAgent, referer, ip, timestamp: new Date().toISOString(), }; // Log redirect details if it's a redirect if (response.status >= 300 && response.status < 400) { logData.redirectLocation = response.headers.get('location'); logger.info('Redirect detected', logData); } else { logger.info('Request completed', logData); } return response; } catch (error) { const duration = Date.now() - startTime; // Log error logger.error('Request failed', { method, url, duration, userAgent, referer, ip, error: error instanceof Error ? error.message : String(error), stack: error instanceof Error ? error.stack : undefined, timestamp: new Date().toISOString(), }); // Re-throw the error to let Next.js handle it throw error; } } export const config = { // Match only internationalized pathnames matcher: ['/((?!api|_next|_vercel|.*\\..*).*)', '/', '/(de|en)/:path*'] };