forked from Samuel1-ona/hunty
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmiddleware.ts
More file actions
90 lines (73 loc) · 2.77 KB
/
Copy pathmiddleware.ts
File metadata and controls
90 lines (73 loc) · 2.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
import createMiddleware from "next-intl/middleware"
import { routing } from "./i18n/routing"
import { NextResponse } from "next/server"
import type { NextRequest } from "next/server"
const intlMiddleware = createMiddleware(routing)
export default function middleware(request: NextRequest) {
// Generate a random cryptographic nonce (Base64)
const nonce = Buffer.from(crypto.randomUUID()).toString("base64")
// Set the nonce in request headers so Server Components can read it
const requestHeaders = new Headers(request.headers)
requestHeaders.set("x-nonce", nonce)
// Create a request proxy or request clone with the new headers
const requestWithNonce = new Proxy(request, {
get(target, prop) {
if (prop === "headers") {
return requestHeaders
}
return Reflect.get(target, prop)
},
})
// Execute next-intl middleware
const response = intlMiddleware(requestWithNonce)
// Configure Content Security Policy
const isProduction = process.env.NODE_ENV === "production"
const isReportOnly = !isProduction || process.env.CSP_REPORT_ONLY === "true"
const ipfsGateways = [
"https://gateway.pinata.cloud",
"https://*.mypinata.cloud",
"https://cloudflare-ipfs.com",
"https://dweb.link",
"https://ipfs.io",
]
const sorobanRpcEndpoints = [
"https://soroban-testnet.stellar.org",
"https://rpc.testnet.soroban.stellar.org",
"https://soroban-mainnet.stellar.org",
"https://rpc.mainnet.soroban.stellar.org",
]
const trustedApis = [
"https://api.resend.com",
"https://torii-indexer.stellar-mainnet.public.blastapi.io",
"https://indexer.testnet.torii.com",
...sorobanRpcEndpoints,
]
const scriptSrc = isProduction
? `script-src 'self' 'nonce-${nonce}'`
: `script-src 'self' 'nonce-${nonce}' 'unsafe-eval'`
const cspDirectives = [
"default-src 'self'",
scriptSrc,
"style-src 'self' 'unsafe-inline'",
`img-src 'self' data: blob: https: ${ipfsGateways.join(" ")}`,
`connect-src 'self' ${trustedApis.join(" ")} wss: https:`,
"font-src 'self' data: https:",
"frame-ancestors 'none'",
"base-uri 'self'",
"form-action 'self'",
"report-uri /api/csp-report",
]
const cspHeaderValue = cspDirectives.join("; ")
const cspHeaderName = isReportOnly ? "Content-Security-Policy-Report-Only" : "Content-Security-Policy"
// Set the CSP response header
response.headers.set(cspHeaderName, cspHeaderValue)
// Set the x-nonce header in the response as well for testing/verification
response.headers.set("x-nonce", nonce)
return response
}
export const config = {
// Match all pathnames except for
// - … if they start with `/api`, `/_next` or `/_vercel`
// - … the ones containing a dot (e.g. `favicon.ico`)
matcher: "/((?!api|_next|_vercel|.*\\..*).*)",
}