old-portfolio-site/src/hooks.server.ts

55 lines
2.6 KiB
TypeScript
Raw Normal View History

2024-04-28 11:44:18 +00:00
import type { Handle } from '@sveltejs/kit'
2024-04-28 12:57:55 +00:00
import { sequence } from '@sveltejs/kit/hooks'
2024-04-28 11:44:18 +00:00
import { site } from '$lib/config/site'
2024-04-04 00:40:30 +00:00
2024-04-28 12:57:55 +00:00
import { handleErrorWithSentry, sentryHandle } from '@sentry/sveltekit'
import * as Sentry from '@sentry/sveltekit'
import { PUBLIC_SENTRY_KEY, PUBLIC_SENTRY_PROJECT_ID, PUBLIC_SENTRY_ORG_ID } from '$env/static/public'
import { csp, rootDomain } from './cspDirectives'
Sentry.init({
dsn: `https://${PUBLIC_SENTRY_KEY}@${PUBLIC_SENTRY_ORG_ID}.ingest.us.sentry.io/${PUBLIC_SENTRY_PROJECT_ID}`,
tracesSampleRate: 1.0
})
export const cspHandle: Handle = async ({ event, resolve }) => {
if (!csp) {
throw new Error('csp is undefined')
}
const response = await resolve(event)
// Permission fullscreen necessary for maps fullscreen
const headers = {
'X-Frame-Options': 'SAMEORIGIN',
'Referrer-Policy': 'no-referrer',
'Permissions-Policy': `accelerometer=(), autoplay=(), camera=(), document-domain=(self, 'js-profiling'), encrypted-media=(), fullscreen=(self ${rootDomain}), gyroscope=(), interest-cohort=(), magnetometer=(), microphone=(), midi=(), payment=(), picture-in-picture=(), publickey-credentials-get=(), sync-xhr=(), usb=(), xr-spatial-tracking=(), geolocation=()`,
'X-Content-Type-Options': 'nosniff',
// 'Content-Security-Policy-Report-Only': csp,
'Content-Security-Policy': csp,
'Strict-Transport-Security': 'max-age=31536000; includeSubDomains; preload',
'Expect-CT': `max-age=86400, report-uri="https://${PUBLIC_SENTRY_ORG_ID}.ingest.us.sentry.io/api/${PUBLIC_SENTRY_PROJECT_ID}/security/?sentry_key=${PUBLIC_SENTRY_KEY}"`,
'Report-To': `{group: "csp-endpoint", "max_age": 10886400, "endpoints": [{"url": "https://${PUBLIC_SENTRY_ORG_ID}.ingest.us.sentry.io/api/${PUBLIC_SENTRY_PROJECT_ID}/security/?sentry_key=${PUBLIC_SENTRY_KEY}"}]}`
}
Object.entries(headers).forEach(([key, value]) => {
response.headers.set(key, value)
})
return response
}
export const langHandle: Handle = async ({ event, resolve }) =>
2024-04-28 11:44:18 +00:00
await resolve(event, {
transformPageChunk: ({ html }) => html.replace('<html lang="en">', `<html lang="${site.lang ?? 'en'}">`)
})
2024-04-28 12:57:55 +00:00
// If you have custom handlers, make sure to place them after `sentryHandle()` in the `sequence` function.
export const handle: Handle = sequence(sentryHandle(), cspHandle, langHandle)
// If you have a custom error handler, pass it to `handleErrorWithSentry`
export const handleError = handleErrorWithSentry()
// https://gist.github.com/acoyfellow/d8e86979c66ebea25e1643594e38be73
// https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP
// https://scotthelme.co.uk/content-security-policy-an-introduction/
// scanner: https://securityheaders.com/