@@ -25,6 +25,23 @@ export type SentryHandleOptions = {
2525 * @default false
2626 */
2727 handleUnknownRoutes ?: boolean ;
28+
29+ /**
30+ * Controls if `sentryHandle` should inject a script tag into the page that enables instrumentation
31+ * of `fetch` calls in `load` functions.
32+ *
33+ * @default true
34+ */
35+ injectFetchProxyScript ?: boolean ;
36+
37+ /**
38+ * If this option is set, the `sentryHandle` handler will add a nonce attribute to the script
39+ * tag it injects into the page. This script is used to enable instrumentation of `fetch` calls
40+ * in `load` functions.
41+ *
42+ * Use this if your CSP policy blocks the fetch proxy script injected by `sentryHandle`.
43+ */
44+ fetchProxyScriptNonce ?: string ;
2845} ;
2946
3047function sendErrorToSentry ( e : unknown ) : unknown {
@@ -53,30 +70,51 @@ function sendErrorToSentry(e: unknown): unknown {
5370 return objectifiedErr ;
5471}
5572
56- const FETCH_PROXY_SCRIPT = `
73+ /**
74+ * Exported only for testing
75+ */
76+ export const FETCH_PROXY_SCRIPT = `
5777 const f = window.fetch;
5878 if(f){
5979 window._sentryFetchProxy = function(...a){return f(...a)}
6080 window.fetch = function(...a){return window._sentryFetchProxy(...a)}
6181 }
6282` ;
6383
64- export const transformPageChunk : NonNullable < ResolveOptions [ 'transformPageChunk' ] > = ( { html } ) => {
65- const transaction = getActiveTransaction ( ) ;
66- if ( transaction ) {
67- const traceparentData = transaction . toTraceparent ( ) ;
68- const dynamicSamplingContext = dynamicSamplingContextToSentryBaggageHeader ( transaction . getDynamicSamplingContext ( ) ) ;
69- const content = `<head>
70- <meta name="sentry-trace" content="${ traceparentData } "/>
71- <meta name="baggage" content="${ dynamicSamplingContext } "/>
72- <script>${ FETCH_PROXY_SCRIPT }
73- </script>
74- ` ;
75- return html . replace ( '<head>' , content ) ;
76- }
84+ /**
85+ * Adds Sentry tracing <meta> tags to the returned html page.
86+ * Adds Sentry fetch proxy script to the returned html page if enabled in options.
87+ * Also adds a nonce attribute to the script tag if users specified one for CSP.
88+ *
89+ * Exported only for testing
90+ */
91+ export function addSentryCodeToPage ( options : SentryHandleOptions ) : NonNullable < ResolveOptions [ 'transformPageChunk' ] > {
92+ const { fetchProxyScriptNonce, injectFetchProxyScript } = options ;
93+ // if injectFetchProxyScript is not set, we default to true
94+ const shouldInjectScript = injectFetchProxyScript !== false ;
95+ const nonce = fetchProxyScriptNonce ? `nonce="${ fetchProxyScriptNonce } "` : '' ;
7796
78- return html ;
79- } ;
97+ return ( { html } ) => {
98+ const transaction = getActiveTransaction ( ) ;
99+ if ( transaction ) {
100+ const traceparentData = transaction . toTraceparent ( ) ;
101+ const dynamicSamplingContext = dynamicSamplingContextToSentryBaggageHeader (
102+ transaction . getDynamicSamplingContext ( ) ,
103+ ) ;
104+ const contentMeta = `<head>
105+ <meta name="sentry-trace" content="${ traceparentData } "/>
106+ <meta name="baggage" content="${ dynamicSamplingContext } "/>
107+ ` ;
108+ const contentScript = shouldInjectScript ? `<script ${ nonce } >${ FETCH_PROXY_SCRIPT } </script>` : '' ;
109+
110+ const content = `${ contentMeta } \n${ contentScript } ` ;
111+
112+ return html . replace ( '<head>' , content ) ;
113+ }
114+
115+ return html ;
116+ } ;
117+ }
80118
81119/**
82120 * A SvelteKit handle function that wraps the request for Sentry error and
@@ -89,13 +127,14 @@ export const transformPageChunk: NonNullable<ResolveOptions['transformPageChunk'
89127 *
90128 * export const handle = sentryHandle();
91129 *
92- * // Optionally use the sequence function to add additional handlers.
130+ * // Optionally use the ` sequence` function to add additional handlers.
93131 * // export const handle = sequence(sentryHandle(), yourCustomHandler);
94132 * ```
95133 */
96134export function sentryHandle ( handlerOptions ?: SentryHandleOptions ) : Handle {
97135 const options = {
98136 handleUnknownRoutes : false ,
137+ injectFetchProxyScript : true ,
99138 ...handlerOptions ,
100139 } ;
101140
@@ -139,7 +178,9 @@ async function instrumentHandle(
139178 } ,
140179 } ,
141180 async ( span ?: Span ) => {
142- const res = await resolve ( event , { transformPageChunk } ) ;
181+ const res = await resolve ( event , {
182+ transformPageChunk : addSentryCodeToPage ( options ) ,
183+ } ) ;
143184 if ( span ) {
144185 span . setHttpStatus ( res . status ) ;
145186 }
0 commit comments