2026-03-15 07:32:42 +01:00
import { NextResponse } from 'next/server' ;
import type { NextRequest } from 'next/server' ;
export function middleware ( request : NextRequest ) {
const nonce = Buffer . from ( crypto . randomUUID ( ) ) . toString ( 'base64' ) ;
// Define CSP directives
const cspDirectives = [
"default-src 'self'" ,
` script-src 'self' 'nonce- ${ nonce } ' 'strict-dynamic' 'unsafe-inline' ` , // 'unsafe-inline' is ignored by modern browsers if nonce/strict-dynamic is present, but kept for fallback
"style-src 'self' 'unsafe-inline' https://fonts.googleapis.com https://unpkg.com" ,
"font-src 'self' https://fonts.gstatic.com" ,
"img-src 'self' data: blob: https://*.basemaps.cartocdn.com https://*.tile.openstreetmap.org https://unpkg.com" ,
"connect-src 'self' https://fonts.googleapis.com https://fonts.gstatic.com" ,
"frame-ancestors 'none'" ,
"base-uri 'self'" ,
"form-action 'self'" ,
] . join ( '; ' ) ;
const requestHeaders = new Headers ( request . headers ) ;
requestHeaders . set ( 'x-nonce' , nonce ) ;
requestHeaders . set ( 'Content-Security-Policy' , cspDirectives ) ;
const response = NextResponse . next ( {
request : {
headers : requestHeaders ,
} ,
} ) ;
response . headers . set ( 'Content-Security-Policy' , cspDirectives ) ;
2026-03-27 11:11:23 +01:00
response . headers . set ( 'X-DNS-Prefetch-Control' , 'on' ) ;
response . headers . set ( 'Strict-Transport-Security' , 'max-age=31536000; includeSubDomains; preload' ) ;
response . headers . set ( 'X-Frame-Options' , 'SAMEORIGIN' ) ;
response . headers . set ( 'X-Content-Type-Options' , 'nosniff' ) ;
response . headers . set ( 'Referrer-Policy' , 'origin-when-cross-origin' ) ;
response . headers . set ( 'Permissions-Policy' , 'camera=(), microphone=(), geolocation=()' ) ;
2026-03-15 07:32:42 +01:00
return response ;
}
export const config = {
matcher : [
/ *
* Match all request paths except for the ones starting with :
* - api ( API routes )
* - _next / static ( static files )
* - _next / image ( image optimization files )
* - favicon . ico , sitemap . xml , robots . txt ( metadata files )
* /
{
source : '/((?!api|_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)' ,
missing : [
{ type : 'header' , key : 'next-router-prefetch' } ,
{ type : 'header' , key : 'purpose' , value : 'prefetch' } ,
] ,
} ,
] ,
} ;