Skip to content

Commit 89a5b2c

Browse files
committed
feat(core): Serve a fixed managed tunnel path from a relative tunnel on the server
A relative `tunnel` can't be a transport URL on the server, so it now names the path the server serves, and `TunnelOptions.path` overrides the DSN-derived path. `tunnel: '/monitor'` on both sides then gives a fixed path the same way `tunnel: true` gives the DSN-derived one.
1 parent e77835f commit 89a5b2c

3 files changed

Lines changed: 24 additions & 1 deletion

File tree

‎packages/core/src/types/options.ts‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -661,6 +661,9 @@ export interface TunnelOptions {
661661
*/
662662
allowedDsns?: string[];
663663

664+
/** A fixed tunnel path instead of the one derived from the DSN. A relative `tunnel` string sets this. */
665+
path?: string;
666+
664667
/** Path prefix the app is served under, e.g. `/docs`. Set the same value in the browser and the server `init`. */
665668
basePath?: string;
666669

‎packages/core/src/utils/tunnel.ts‎

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,15 @@ export function resolveServerTunnelOption(tunnel: string | true | TunnelOptions
2727
tunnel: string | undefined;
2828
_managedTunnel?: TunnelOptions;
2929
} {
30-
if (typeof tunnel === 'string' || !tunnel) {
30+
if (!tunnel) {
3131
return { tunnel };
3232
}
3333

34+
if (typeof tunnel === 'string') {
35+
// A relative path can't be a transport URL on the server, so it names the path to serve instead.
36+
return tunnel.startsWith('/') ? { tunnel: undefined, _managedTunnel: { path: tunnel } } : { tunnel };
37+
}
38+
3439
return { tunnel: undefined, _managedTunnel: tunnel === true ? {} : tunnel };
3540
}
3641

@@ -77,6 +82,10 @@ export function getTunnelPaths(options?: TunnelOptions): string[] {
7782
return [];
7883
}
7984

85+
if (tunnelOptions.path) {
86+
return [tunnelOptions.path];
87+
}
88+
8089
return resolveAllowedDsns(tunnelOptions.allowedDsns)
8190
.map(dsn => getTunnelPath(dsn))
8291
.filter((path): path is string => !!path);

‎packages/core/test/lib/utils/tunnel.test.ts‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,13 @@ describe('getTunnelPaths', () => {
295295
]);
296296
});
297297

298+
it('returns a fixed path instead of the DSN-derived ones', () => {
299+
expect(getTunnelPaths({ path: '/monitor', allowedDsns: [TEST_DSN] })).toEqual(['/monitor']);
300+
expect(isTunnelRequest({ method: 'POST', url: '/monitor' }, { path: '/monitor', allowedDsns: [TEST_DSN] })).toBe(
301+
true,
302+
);
303+
});
304+
298305
it('uses the managed tunnel config of the active client', () => {
299306
expect(getTunnelPaths()).toEqual([]);
300307

@@ -366,6 +373,10 @@ describe('resolveServerTunnelOption', () => {
366373
});
367374
});
368375

376+
it('serves a relative path instead of using it as the transport tunnel', () => {
377+
expect(resolveServerTunnelOption('/monitor')).toEqual({ tunnel: undefined, _managedTunnel: { path: '/monitor' } });
378+
});
379+
369380
it('leaves everything off when unset', () => {
370381
expect(resolveServerTunnelOption(undefined)).toEqual({ tunnel: undefined });
371382
});

0 commit comments

Comments
 (0)