@@ -25,6 +25,23 @@ export type SentryHandleOptions = {
25
25
* @default false
26
26
*/
27
27
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 ;
28
45
} ;
29
46
30
47
function sendErrorToSentry ( e : unknown ) : unknown {
@@ -53,30 +70,51 @@ function sendErrorToSentry(e: unknown): unknown {
53
70
return objectifiedErr ;
54
71
}
55
72
56
- const FETCH_PROXY_SCRIPT = `
73
+ /**
74
+ * Exported only for testing
75
+ */
76
+ export const FETCH_PROXY_SCRIPT = `
57
77
const f = window.fetch;
58
78
if(f){
59
79
window._sentryFetchProxy = function(...a){return f(...a)}
60
80
window.fetch = function(...a){return window._sentryFetchProxy(...a)}
61
81
}
62
82
` ;
63
83
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 } "` : '' ;
77
96
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
+ }
80
118
81
119
/**
82
120
* A SvelteKit handle function that wraps the request for Sentry error and
@@ -89,13 +127,14 @@ export const transformPageChunk: NonNullable<ResolveOptions['transformPageChunk'
89
127
*
90
128
* export const handle = sentryHandle();
91
129
*
92
- * // Optionally use the sequence function to add additional handlers.
130
+ * // Optionally use the ` sequence` function to add additional handlers.
93
131
* // export const handle = sequence(sentryHandle(), yourCustomHandler);
94
132
* ```
95
133
*/
96
134
export function sentryHandle ( handlerOptions ?: SentryHandleOptions ) : Handle {
97
135
const options = {
98
136
handleUnknownRoutes : false ,
137
+ injectFetchProxyScript : true ,
99
138
...handlerOptions ,
100
139
} ;
101
140
@@ -139,7 +178,9 @@ async function instrumentHandle(
139
178
} ,
140
179
} ,
141
180
async ( span ?: Span ) => {
142
- const res = await resolve ( event , { transformPageChunk } ) ;
181
+ const res = await resolve ( event , {
182
+ transformPageChunk : addSentryCodeToPage ( options ) ,
183
+ } ) ;
143
184
if ( span ) {
144
185
span . setHttpStatus ( res . status ) ;
145
186
}
0 commit comments