@@ -43,6 +43,10 @@ function getFinalConfigObject(
4343 // Remind TS that there's now no `sentry` property
4444 const userNextConfigObject = incomingUserNextConfigObject as NextConfigObject ;
4545
46+ if ( userSentryOptions ?. tunnelRoute ) {
47+ setUpTunnelRewriteRules ( userNextConfigObject , userSentryOptions . tunnelRoute ) ;
48+ }
49+
4650 // In order to prevent all of our build-time code from being bundled in people's route-handling serverless functions,
4751 // we exclude `webpack.ts` and all of its dependencies from nextjs's `@vercel/nft` filetracing. We therefore need to
4852 // make sure that we only require it at build time or in development mode.
@@ -58,3 +62,52 @@ function getFinalConfigObject(
5862 // At runtime, we just return the user's config untouched.
5963 return userNextConfigObject ;
6064}
65+
66+ /**
67+ * Injects rewrite rules into the Next.js config provided by the user to tunnel
68+ * requests from the `tunnelPath` to Sentry.
69+ *
70+ * See https://nextjs.org/docs/api-reference/next.config.js/rewrites.
71+ */
72+ function setUpTunnelRewriteRules ( userNextConfig : NextConfigObject , tunnelPath : string ) : void {
73+ const originalRewrites = userNextConfig . rewrites ;
74+
75+ // This function doesn't take any arguments at the time of writing but we future-proof
76+ // here in case Next.js ever decides to pass some
77+ userNextConfig . rewrites = async ( ...args : unknown [ ] ) => {
78+ const injectedRewrite = {
79+ // Matched rewrite routes will look like the following: `[tunnelPath]?o=[orgid]&p=[projectid]`
80+ // Nextjs will automatically convert `source` into a regex for us
81+ source : `${ tunnelPath } (/?)` ,
82+ has : [
83+ {
84+ type : 'query' ,
85+ key : 'o' , // short for orgId - we keep it short so matching is harder for ad-blockers
86+ value : '(?<orgid>.*)' ,
87+ } ,
88+ {
89+ type : 'query' ,
90+ key : 'p' , // short for projectId - we keep it short so matching is harder for ad-blockers
91+ value : '(?<projectid>.*)' ,
92+ } ,
93+ ] ,
94+ destination : 'https://o:orgid.ingest.sentry.io/api/:projectid/envelope/' ,
95+ } ;
96+
97+ if ( typeof originalRewrites !== 'function' ) {
98+ return [ injectedRewrite ] ;
99+ }
100+
101+ // @ts -ignore Expected 0 arguments but got 1 - this is from the future-proofing mentioned above, so we don't care about it
102+ const originalRewritesResult = await originalRewrites ( ...args ) ;
103+
104+ if ( Array . isArray ( originalRewritesResult ) ) {
105+ return [ injectedRewrite , ...originalRewritesResult ] ;
106+ } else {
107+ return {
108+ ...originalRewritesResult ,
109+ beforeFiles : [ injectedRewrite , ...originalRewritesResult . beforeFiles ] ,
110+ } ;
111+ }
112+ } ;
113+ }
0 commit comments