Skip to content

Commit 00c287f

Browse files
committed
add wrapper for API routes
1 parent 8525227 commit 00c287f

File tree

3 files changed

+47
-0
lines changed

3 files changed

+47
-0
lines changed

packages/nextjs/src/config/wrappers/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ export { withSentryServerSideAppGetInitialProps } from './withSentryServerSideAp
44
export { withSentryServerSideDocumentGetInitialProps } from './withSentryServerSideDocumentGetInitialProps';
55
export { withSentryServerSideErrorGetInitialProps } from './withSentryServerSideErrorGetInitialProps';
66
export { withSentryGetServerSideProps } from './withSentryGetServerSideProps';
7+
export { withSentryAPI } from './withSentryAPI';
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// We import these types from `withSentry` rather than directly from `next` because our version can work simultaneously
2+
// with multiple versions of next. See note in `withSentry` for more.
3+
import type { NextApiHandler, WrappedNextApiHandler } from '../../utils/withSentry';
4+
import { withSentry } from '../../utils/withSentry';
5+
6+
/**
7+
* Wrap the given API route handler for tracing and error capturing. Thin wrapper around `withSentry`, which only
8+
* applies it if it hasn't already been applied.
9+
*
10+
* @param maybeWrappedHandler The handler exported from the user's API page route file, which may or may not already be
11+
* wrapped with `withSentry`
12+
* @param parameterizedRoute The page's route, passed in via the proxy loader
13+
* @returns
14+
*/
15+
export function withSentryAPI(
16+
maybeWrappedHandler: NextApiHandler | WrappedNextApiHandler,
17+
parameterizedRoute: string,
18+
): WrappedNextApiHandler {
19+
// We want the innards of `withSentry` to have access to the parameterized route, so it can be used when we start the
20+
// request transaction. If we were always the ones calling `withSentry` (the way we're always the ones to call
21+
// `withSentryServerSideProps`, for example), then we could just pass it in as a second parameter and know it would
22+
// always be there. But in the case where users have already manually wrapped their API route handlers with
23+
// `withSentry`, they're the ones calling it, without the parameterized route as a second parameter. We therefore need
24+
// a different way to make it available, which we'll do by storing it on the handler or handler wrapper, depending on
25+
// what we're given.
26+
maybeWrappedHandler.__sentry_route__ = parameterizedRoute;
27+
28+
// In the simple case, where the handler has not yet been wrapped, `maybeWrappedHandler` will be passed to
29+
// `withSentry` as `origHandler` and so the parameterized route will be easy to access.
30+
if (!('__sentry_wrapped__' in maybeWrappedHandler)) {
31+
return withSentry(maybeWrappedHandler);
32+
}
33+
34+
// In the case where the exported handler is already of the form `withSentry(origHandler)`, `maybeWrappedHandler` is
35+
// the wrapped handler returned by `withSentry`, which now has the parameterized route as a property on itself. By
36+
// default in JS, functions have `global` as their `this` value, so to be able to get at the route value, we need to
37+
// make sure it's called with itself as `this`. Since ultimately we need to give nextjs something *it* will call (and
38+
// it won't set the `this` value we want when it does), this means one more wrapper.
39+
const newWrapper: WrappedNextApiHandler = (req, res) => {
40+
// Make `maybeyWrappedHandler` its own `this`
41+
return maybeWrappedHandler.call(maybeWrappedHandler, req, res);
42+
};
43+
44+
return newWrapper;
45+
}

packages/nextjs/src/index.server.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ export {
134134
withSentryServerSideAppGetInitialProps,
135135
withSentryServerSideDocumentGetInitialProps,
136136
withSentryServerSideErrorGetInitialProps,
137+
withSentryAPI,
137138
} from './config/wrappers';
138139
export { withSentry } from './utils/withSentry';
139140

0 commit comments

Comments
 (0)