Repository navigation
ref: Remove the framework tunnel hooks #26001
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,33 +1,12 @@ | ||
| import { | ||
| _INTERNAL_handleServedTunnelRequest as handleServedTunnelRequest, | ||
| _INTERNAL_isServedTunnelRequest as isServedTunnelRequest, | ||
| _INTERNAL_setTunnelDefaults as setTunnelDefaults, | ||
| } from '@sentry/core/server'; | ||
| import { eventHandler, toWebRequest } from 'h3'; | ||
| import { _INTERNAL_setTunnelDefaults as setTunnelDefaults } from '@sentry/core/server'; | ||
| import type { NitroAppPlugin } from 'nitropack'; | ||
| import { useRuntimeConfig } from 'nitropack/runtime'; | ||
|
|
||
| /** | ||
| * Answers managed tunnel requests on Nuxt v3 and v4 (Nitro v2), from the first layer of the h3 app. That runs | ||
| * before route rules and the app's `server/middleware`. | ||
| * Serves the managed tunnel under Nuxt's `app.baseURL` on Nuxt v3 and v4 (Nitro v2). The runtime answers the | ||
| * requests. | ||
| */ | ||
| export default (nitroApp => { | ||
| // The first layer sees the path before Nitro strips `app.baseURL`, so the tunnel is served under it. | ||
| export default (() => { | ||
| // `useRuntimeConfig` also picks up a `NUXT_APP_BASE_URL` set at runtime, the same value the browser gets. | ||
| setTunnelDefaults({ basePath: useRuntimeConfig().app?.baseURL }); | ||
|
|
||
| // Not the `request` hook: h3 still runs the first layer after a hook answered, and with a `headers` route rule | ||
| // that layer throws for writing headers on the sent response. | ||
| nitroApp.h3App.stack.unshift({ | ||
| route: '', | ||
| handler: eventHandler(event => { | ||
| // Checked on the method and path first, so no other request's body gets wrapped in a web `Request`. | ||
| if (!isServedTunnelRequest({ method: event.method, url: event.path })) { | ||
| return undefined; | ||
| } | ||
|
|
||
| // A returned `Response` is sent and ends the request, while `undefined` hands it to the next layer. | ||
| return handleServedTunnelRequest(toWebRequest(event)); | ||
| }), | ||
| }); | ||
| }) satisfies NitroAppPlugin; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,20 +1,11 @@ | ||
| import { | ||
| _INTERNAL_handleServedTunnelRequest as handleServedTunnelRequest, | ||
| _INTERNAL_setTunnelDefaults as setTunnelDefaults, | ||
| } from '@sentry/core/server'; | ||
| import { _INTERNAL_setTunnelDefaults as setTunnelDefaults } from '@sentry/core/server'; | ||
| import { useRuntimeConfig } from 'nitro/runtime-config'; | ||
| import type { NitroAppPlugin, NitroApp } from 'nitro/types'; | ||
| import type { NitroAppPlugin } from 'nitro/types'; | ||
|
|
||
| /** | ||
| * Answers managed tunnel requests on Nuxt v5+ (Nitro v3+). | ||
| * Serves the managed tunnel under Nuxt's `app.baseURL` on Nuxt v5+ (Nitro v3+). The runtime answers the requests. | ||
| */ | ||
| export default ((nitroApp: NitroApp) => { | ||
| // Nitro runs the app's `server/middleware` before anything a module registers, so an auth middleware there would | ||
| // block the tunnel. Every preset hands requests to `nitroApp.fetch` after the plugins ran, so wrapping it goes | ||
| // first, before route rules and middleware. | ||
| // Requests still carry Nuxt's `app.baseURL` here, so the tunnel is served under it. `useRuntimeConfig` also picks | ||
| // up a `NUXT_APP_BASE_URL` set at runtime. | ||
| export default (() => { | ||
| // `useRuntimeConfig` also picks up a `NUXT_APP_BASE_URL` set at runtime, the same value the browser gets. | ||
| setTunnelDefaults({ basePath: (useRuntimeConfig() as { app?: { baseURL?: string } }).app?.baseURL }); | ||
| const appFetch = nitroApp.fetch; | ||
| nitroApp.fetch = request => handleServedTunnelRequest(request) ?? appFetch(request); | ||
| }) satisfies NitroAppPlugin; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,7 +9,7 @@ export { createSentryHandleRequest, type SentryHandleRequestOptions } from './cr | |
| export type { SentryWebStreamHandleRequestOptions } from './handleRequestTypes'; | ||
| export { createSentryHandleError, type SentryHandleErrorOptions } from './createSentryHandleError'; | ||
| export { getMetaTagTransformer } from './getMetaTagTransformer'; | ||
| export { createSentryTunnelRoutes } from './tunnelRoute'; | ||
| export { setTunnelBasePath as _INTERNAL_setTunnelBasePath } from './tunnelRoute'; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Public tunnel route helper removedMedium Severity
Additional Locations (1)Triggered by project rule: PR Review Guidelines for Cursor Bot Reviewed by Cursor Bugbot for commit 53c1064. Configure here. |
||
|
|
||
| // React Router instrumentation API support | ||
| export { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,70 +1,12 @@ | ||
| import { debug, getClient } from '@sentry/core'; | ||
| import { | ||
| _INTERNAL_getTunnelPaths as getTunnelPaths, | ||
| _INTERNAL_handleServedTunnelRequest as handleServedTunnelRequest, | ||
| _INTERNAL_setTunnelDefaults as setTunnelDefaults, | ||
| } from '@sentry/core/server'; | ||
| import { DEBUG_BUILD } from '../common/debug-build'; | ||
|
|
||
| // Never matches a request, for when the managed tunnel is off. | ||
| const DISABLED_TUNNEL_PATH = '/__sentry-tunnel-disabled__'; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Tunnel missing on serverless adaptersHigh Severity These frameworks now only call Additional Locations (2)Reviewed by Cursor Bugbot for commit 53c1064. Configure here. |
||
| import { _INTERNAL_setTunnelDefaults as setTunnelDefaults } from '@sentry/core/server'; | ||
|
|
||
| /** | ||
| * The resource routes that serve the managed tunnel, one per tunnel path. `sentryReactRouter()` adds them to the | ||
| * server build, since React Router has no request hook to answer from and a route matches only one path. Not meant | ||
| * to be used directly. | ||
| * Serves the managed tunnel under the app's `basename`, which React Router leaves in the request URL. | ||
| * `sentryReactRouter()` calls it from the server build. | ||
| * | ||
| * @param basename The app's `basename`, which React Router matches the routes under but leaves in the request URL. | ||
| * @param basename The app's `basename`. | ||
| */ | ||
| export function createSentryTunnelRoutes(basename?: string): Record<string, Record<string, unknown>> { | ||
| export function setTunnelBasePath(basename?: string): void { | ||
| // Runs when the server build loads. Clients created later, e.g. per request on Cloudflare, start with the basename. | ||
| setTunnelDefaults({ basePath: basename }); | ||
|
|
||
| // `init` runs from `--import` before the server build loads, so the client and its tunnel paths are usually known. | ||
| if (!getClient()) { | ||
| return { 'sentry-tunnel': makeTunnelRoute('sentry-tunnel', getLazyTunnelPath) }; | ||
| } | ||
|
|
||
| return Object.fromEntries( | ||
| getTunnelPaths().map((path, index) => { | ||
| const id = `sentry-tunnel-${index}`; | ||
|
|
||
| return [id, makeTunnelRoute(id, () => path)]; | ||
| }), | ||
| ); | ||
| } | ||
|
|
||
| /** | ||
| * The path of the single route added when `init` runs after the server build loads, e.g. per request on Cloudflare. | ||
| * React Router reads it on its first request and keeps it until the server restarts. | ||
| */ | ||
| function getLazyTunnelPath(): string { | ||
| if (!getClient()) { | ||
| DEBUG_BUILD && debug.warn('The managed tunnel stays off until restart: a request came in before `Sentry.init`.'); | ||
| return DISABLED_TUNNEL_PATH; | ||
| } | ||
|
|
||
| const [path, ...otherPaths] = getTunnelPaths(); | ||
| if (otherPaths.length) { | ||
| DEBUG_BUILD && debug.warn(`Sentry.init ran after the server build loaded, so only ${path} is served.`); | ||
| } | ||
|
|
||
| return path ?? DISABLED_TUNNEL_PATH; | ||
| } | ||
|
|
||
| function makeTunnelRoute(id: string, getPath: () => string): Record<string, unknown> { | ||
| return { | ||
| id, | ||
| parentId: undefined, | ||
| index: undefined, | ||
| caseSensitive: undefined, | ||
| get path(): string { | ||
| return getPath(); | ||
| }, | ||
| module: { | ||
| action: ({ request }: { request: Request }) => | ||
| handleServedTunnelRequest(request) ?? new Response(null, { status: 404 }), | ||
| loader: () => new Response(null, { status: 405, headers: { Allow: 'POST' } }), | ||
| }, | ||
| }; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| import type { Plugin } from 'vite'; | ||
|
|
||
| const SERVER_BUILD_MODULE_ID = 'virtual:react-router/server-build'; | ||
|
|
||
| /** | ||
| * Passes the app's `basename` from the server build to the managed tunnel, which serves under it. Only applies when | ||
| * `serveTunnelIntegration` is set up. | ||
| */ | ||
| export function makeTunnelBasePathPlugin(): Plugin { | ||
| return { | ||
| name: 'sentry-react-router-tunnel-base-path', | ||
| enforce: 'post', | ||
|
|
||
| transform(code, id, options) { | ||
| if (!options?.ssr || !id.includes(SERVER_BUILD_MODULE_ID)) { | ||
| return null; | ||
| } | ||
|
|
||
| return { | ||
| code: `${code} | ||
| import { _INTERNAL_setTunnelBasePath as __sentrySetTunnelBasePath } from '@sentry/react-router'; | ||
| __sentrySetTunnelBasePath(typeof basename === 'string' ? basename : undefined); | ||
| `, | ||
| map: null, | ||
| }; | ||
| }, | ||
| }; | ||
| } |
This file was deleted.


Uh oh!
There was an error while loading. Please reload this page.