Repository navigation
feat(core): Add managed tunnel helpers that derive the tunnel path from the DSN - #25199
Conversation
af27973 to
a2af1e1
Compare
c544ac0 to
89a5b2c
Compare
size-limit report 📦Compared: e7eedd7 (PR test merge using develop at d4a4e81) Against: ca4fc32 (develop) · base run #62950
|
3bba67e to
4eea4c9
Compare
|
bugbot run |
|
bugbot run |
1 similar comment
|
bugbot run |
a9a04bc to
d53b981
Compare
8e34dd6 to
f97d8a2
Compare
#25515's 411 and 413 checks run before the header line is read, so an oversized or unlengthed request is rejected without reading its body.
… ignore a root one
…ne written with a secret key still matches
feae0ed to
98ff881
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 98ff881. Configure here.
Lms24
left a comment
There was a problem hiding this comment.
Given @JPeer264 thorough review, I mainly focused on the forwarding logic itself and had some suggestions for the max size check and forwarding more headers.
I'm +1 for making the browser- and server-specific options browser/server client specific to avoid confusion.
…25200) Previously the client side only accepted a `string` tunnel option so it sent the requests to that fixed endpoint, this PR effectively adds "managed" tunnel support that is generated automatically from the provided DSN. This PR adds the tunnel options to the SDKs's `init` options and implements the client transport if the tunnel is provided. On the server side the runtime SDKs only translate `tunnel: true` into the internal `_managedTunnel` option, answering the requests is left to the meta-frameworks in the rest of the stack. For reviewers: if you need an overview of what this is, refer to #25199. closes #25460
…ntry (#25408) TanStack Start picked a random tunnel path per build and patched the generated route tree to serve it. Because the new approach relies less on build-time, the logic was changed to wrap the server entrypoint instead and only route the matching tunnel requests to our handler. The tradeoff is that every app using `sentryTanstackStart()` gets its server entry wrapped, tunnel or not, since `serveTunnelIntegration()` turns the tunnel on at runtime. The original entry then loads through a `?sentry-tunnel-original` id, and without a tunnel each request only pays one lookup. This isn't a breaking change, previously we injected a single endpoint handler, now we inject a middleware since the DSN is only known at runtime. The base path comes from `router.basepath` (or Vite's `base`), and the `tunnel-basepath` e2e variants cover it in both dev and prod. For reviewers: if you need an overview of what this is, refer to #25199. closes #25461
…uests (#25414) Runtimes only translate `tunnel: true` while meta-frameworks answer the requests, so nothing pinned down that their server spans get dropped. This PR asserts that runtime SDKs level (Cloudflare, Node, Bun and Deno) ignores the tunneled span so we don't have to chase it around. This is one benefit of having tunnels as a core SDK capability, this PR just tests that. Node, Deno and Cloudflare live in their integration test suites, and Bun is a unit test in its package. For reviewers: if you need an overview of what this is, refer to #25199. closes #25462
…he app's base path (#25415) Implements sveltekit tunnel wiring, the way it works is: - Our Vite plugin injects the base path (`kit.paths.base`) if it exists to both server/client bundles. - Our entry handler (`sentryHandle`) will check for any incoming request if it is a tunneled one, and if it matches it handles it. _(I made the decision to respect base paths rather than ignoring them, this is something to review in #25199)_ This also adds a couple of shared e2e helpers to `@sentry-internal/test-utils` that the rest of the stack uses. The `sveltekit-3` tunnel variants cover dev and prod, and there's one for Cloudflare Workers too. For reviewers: if you need an overview of what this is, refer to #25199. closes #20256
…iddleware (#25418) A Nitro app's own `server/middleware`, like an auth check, ran before anything Sentry registered and would block tunnel requests, fixed by putting the tunnel check first in h3's middleware on Nitro v3 and answering from the `request` hook on Nitro v2. This is the one framework PR where the ordering matters, so worth a closer look. Nuxt picks the right plugin based on the Nitro version, and the base path comes from Nitro's `baseURL`. The e2e tunnel variants for Nuxt 4, Nuxt 5 and Nitro 3 check that the tunnel answers while an auth middleware rejects every other POST. For reviewers: if you need an overview of what this is, refer to #25199. closes #20254
) This PR adds the tunnel wiring to the astro SDK. We already had a global middleware active, so it works by adding logic to check if the incoming request is a tunnel request and if it is, then it will be handled. The server init now also runs from the integration's middleware entry, so the first request is instrumented even when it hits a prerendered page first, which also fixes server islands after a prerendered page. This also respects the decision made earlier to follow the base path configured by the user, which comes from Astro's `base` config. The `astro-7` and `astro-6-cf-workers` tunnel variants cover node and Cloudflare. For reviewers: if you need an overview of what this is, refer to #25199. closes #25463
…er build (#25422) React Router has no request hook, so to wire the tunnel logic, we add a resource route to the server build whose path comes from the DSN at runtime. The base path is the app's `basename`, which the server build already exports. The `tunnel-basepath` e2e variants cover dev, prod and Cloudflare. For reviewers: if you need an overview of what this is, refer to #25199. closes #20255
This PR wires SolidStart's SDK tunnel by adding a nitro 2 plugin that adds a request hook to handle tunneled requests. The base path comes from `server.baseURL`, and the `tunnel-basepath` e2e variants cover dev and prod. For reviewers: if you need an overview of what this is, refer to #25199. closes #25465

Overview
SDK Tunnel is a feature that allows client SDKs (e.g: browser) to send their requests through an endpoint that lives on the user's own application that forwards to Sentry. This bypasses adblockers and similar extensions.
Tunnels could be configured as a fixed endpoint defined by the user (defaulted to
/monitoring) but that usually ends up in global adblocker lists. Alternatively, users can tell the SDK to use a random endpoint to bypass that.Previously the tunnel logic mostly lived in client bundles and in server frameworks build time, this had two issues:
This stack of PRs re-works the idea by moving to more stable yet random URL generation based on the client's DSN and moves the tunnel handling into the runtime of the core SDK.
Meaning tunneling now is a core SDK capability rather than a meta framework feature.
Here is how it looks for users:
And a tunneled request goes like this: the framework hook calls
handleTunnelRequestIfMatched, if the path matches it checks the envelope's DSN against the allowed ones and forwards it to Sentry, otherwise the request continues as normal.This PR
This sets up the core for the new tunnel mechanism that the rest of the stack will be implemented against, it does the following:
It also sets up a couple of key decisions that will carry over throughout the stack:
/appas a base path our tunnels handlers will expect that prefix.allowedDSNson the server, this correction only applies if the client and server share the same DSN, if there is a different DSN involved then it is on the user to configure that correctly. Will work on documenting this.Reviewing the stack
This PR and #25200 are where the actual behavior lives so these need the closest look, mainly
forwardEnvelopeand the base path handling intunnel.ts.The framework PRs all follow the same pattern: find the earliest request hook the framework gives us, call the core handler there, and pass the framework's base path along. They are small, so ideally whoever knows that framework best picks it up:
sentryHandleunder the app's base path #25415#25414 is tests only, and Next.js #25424 is on hold, I will split it up before it's ready.