Skip to content

Commit

Permalink
feat(nextjs/v7): Support Hybrid Cloud DSNs with tunnelRoute option (#…
Browse files Browse the repository at this point in the history
…10958)

Co-authored-by: Alexander Tarasov <[email protected]>
Fixes #10948
  • Loading branch information
lforst authored Mar 7, 2024
1 parent 7ad8957 commit 369fc52
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 6 deletions.
8 changes: 6 additions & 2 deletions packages/nextjs/src/client/tunnelRoute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,14 @@ export function applyTunnelRouteOption(options: BrowserOptions): void {
if (!dsnComponents) {
return;
}
const sentrySaasDsnMatch = dsnComponents.host.match(/^o(\d+)\.ingest\.sentry\.io$/);
const sentrySaasDsnMatch = dsnComponents.host.match(/^o(\d+)\.ingest(?:\.([a-z]{2}))?\.sentry\.io$/);
if (sentrySaasDsnMatch) {
const orgId = sentrySaasDsnMatch[1];
const tunnelPath = `${tunnelRouteOption}?o=${orgId}&p=${dsnComponents.projectId}`;
const regionCode = sentrySaasDsnMatch[2];
let tunnelPath = `${tunnelRouteOption}?o=${orgId}&p=${dsnComponents.projectId}`;
if (regionCode) {
tunnelPath += `&r=${regionCode}`;
}
options.tunnel = tunnelPath;
DEBUG_BUILD && logger.info(`Tunneling events to "${tunnelPath}"`);
} else {
Expand Down
32 changes: 28 additions & 4 deletions packages/nextjs/src/config/withSentryConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ function setUpTunnelRewriteRules(userNextConfig: NextConfigObject, tunnelPath: s
// This function doesn't take any arguments at the time of writing but we future-proof
// here in case Next.js ever decides to pass some
userNextConfig.rewrites = async (...args: unknown[]) => {
const injectedRewrite = {
const tunnelRouteRewrite = {
// Matched rewrite routes will look like the following: `[tunnelPath]?o=[orgid]&p=[projectid]`
// Nextjs will automatically convert `source` into a regex for us
source: `${tunnelPath}(/?)`,
Expand All @@ -115,19 +115,43 @@ function setUpTunnelRewriteRules(userNextConfig: NextConfigObject, tunnelPath: s
destination: 'https://o:orgid.ingest.sentry.io/api/:projectid/envelope/?hsts=0',
};

const tunnelRouteRewriteWithRegion = {
// Matched rewrite routes will look like the following: `[tunnelPath]?o=[orgid]&p=[projectid]?r=[region]`
// Nextjs will automatically convert `source` into a regex for us
source: `${tunnelPath}(/?)`,
has: [
{
type: 'query',
key: 'o', // short for orgId - we keep it short so matching is harder for ad-blockers
value: '(?<orgid>\\d*)',
},
{
type: 'query',
key: 'p', // short for projectId - we keep it short so matching is harder for ad-blockers
value: '(?<projectid>\\d*)',
},
{
type: 'query',
key: 'r', // short for region - we keep it short so matching is harder for ad-blockers
value: '(?<region>\\[a-z\\]{2})',
},
],
destination: 'https://o:orgid.ingest.:region.sentry.io/api/:projectid/envelope/?hsts=0',
};

if (typeof originalRewrites !== 'function') {
return [injectedRewrite];
return [tunnelRouteRewriteWithRegion, tunnelRouteRewrite];
}

// @ts-expect-error Expected 0 arguments but got 1 - this is from the future-proofing mentioned above, so we don't care about it
const originalRewritesResult = await originalRewrites(...args);

if (Array.isArray(originalRewritesResult)) {
return [injectedRewrite, ...originalRewritesResult];
return [tunnelRouteRewriteWithRegion, tunnelRouteRewrite, ...originalRewritesResult];
} else {
return {
...originalRewritesResult,
beforeFiles: [injectedRewrite, ...(originalRewritesResult.beforeFiles || [])],
beforeFiles: [tunnelRouteRewriteWithRegion, tunnelRouteRewrite, ...(originalRewritesResult.beforeFiles || [])],
};
}
};
Expand Down
11 changes: 11 additions & 0 deletions packages/nextjs/test/utils/tunnelRoute.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,15 @@ describe('applyTunnelRouteOption()', () => {

expect(options.tunnel).toBeUndefined();
});

it('Correctly applies `tunnelRoute` option to region DSNs', () => {
globalWithInjectedValues.__sentryRewritesTunnelPath__ = '/my-error-monitoring-route';
const options: any = {
dsn: 'https://[email protected]/3333333',
} as BrowserOptions;

applyTunnelRouteOption(options);

expect(options.tunnel).toBe('/my-error-monitoring-route?o=2222222&p=3333333&r=us');
});
});

0 comments on commit 369fc52

Please sign in to comment.