feat(node): Ensure request bodies are reliably captured for http requests
This PR started out as trying to fix capturing request bodies for Koa.
Some investigation later, we found out that the fundamental problem was that we relied on the request body being on request.body, which is non-standard and thus does not necessarily works. It seems that in express this works because it under the hood writes the body there, but this is non-standard and rather undefined behavior. For other frameworks (e.g. Koa and probably more) this did not work, the body was not on the request and thus never captured. We also had no test coverage for this overall.
This PR ended up doing a few things:
- Add tests for this for express and koa
- Streamline types for
sdkProcessingMetadata- this used to beany, which lead to any usage of this not really being typed at all. I added proper types for this now. - Generic extraction of the http request body in the http instrumentation - this should now work for any node framework
Most importantly, I opted to not force this into the existing, rather complicated and hard to follow request data integration flow. This used to take an IsomorphicRequest and then did a bunch of conversion etc.
Since now in Node, we always have the same, proper http request (for any framework, because this always goes through http instrumentation), we can actually streamline this and normalize this properly at the time where we set this.
So with this PR, we set a normalizedRequest which already has the url, headers etc. set in a way that we need it/it makes sense.
Additionally, the parsed & stringified request body will be set on this too.
If this normalized request is set in sdkProcessingMetadata, we will use it as source of truth instead of the plain request. (Note that we still need the plain request for some auxiliary data that is non-standard, e.g. request.user).
For the body parsing itself, we monkey-patch req.on('data'). this way, we ensure to not add more handlers than a user has, and we only extract the body if the user is extracting it anyhow, ensuring we do not alter behavior.
Closes https://github.com/getsentry/sentry-javascript/issues/13722
size-limit report 📦
⚠️ Warning: Base artifact is not the latest one, because the latest workflow run is not done yet. This may lead to incorrect results. Try to re-run all tests to get up to date results.
| Path | Size | % Change | Change |
|---|---|---|---|
| @sentry/browser | 22.77 KB | - | - |
| @sentry/browser - with treeshaking flags | 21.53 KB | - | - |
| @sentry/browser (incl. Tracing) | 35.26 KB | - | - |
| @sentry/browser (incl. Tracing, Replay) | 71.98 KB | - | - |
| @sentry/browser (incl. Tracing, Replay) - with treeshaking flags | 62.35 KB | - | - |
| @sentry/browser (incl. Tracing, Replay with Canvas) | 76.31 KB | - | - |
| @sentry/browser (incl. Tracing, Replay, Feedback) | 89.14 KB | - | - |
| @sentry/browser (incl. Feedback) | 39.93 KB | - | - |
| @sentry/browser (incl. sendFeedback) | 27.42 KB | - | - |
| @sentry/browser (incl. FeedbackAsync) | 32.23 KB | - | - |
| @sentry/react | 25.52 KB | - | - |
| @sentry/react (incl. Tracing) | 38.22 KB | - | - |
| @sentry/vue | 26.91 KB | - | - |
| @sentry/vue (incl. Tracing) | 37.1 KB | - | - |
| @sentry/svelte | 22.91 KB | - | - |
| CDN Bundle | 24.13 KB | - | - |
| CDN Bundle (incl. Tracing) | 37.04 KB | - | - |
| CDN Bundle (incl. Tracing, Replay) | 71.7 KB | - | - |
| CDN Bundle (incl. Tracing, Replay, Feedback) | 77.05 KB | - | - |
| CDN Bundle - uncompressed | 70.73 KB | - | - |
| CDN Bundle (incl. Tracing) - uncompressed | 109.9 KB | - | - |
| CDN Bundle (incl. Tracing, Replay) - uncompressed | 222.42 KB | - | - |
| CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed | 235.64 KB | - | - |
| @sentry/nextjs (client) | 38.33 KB | - | - |
| @sentry/sveltekit (client) | 35.84 KB | - | - |
| @sentry/node | 134.28 KB | +0.59% | +798 B 🔺 |
| @sentry/node - without tracing | 96.46 KB | +0.83% | +807 B 🔺 |
| @sentry/aws-serverless | 106.72 KB | +0.74% | +802 B 🔺 |
:x: 1 Tests Failed:
| Tests completed | Failed | Passed | Skipped |
|---|---|---|---|
| 637 | 1 | 636 | 33 |
View the top 1 failed tests by shortest run time
transactions.test.ts Captures request metadataStack Traces | 0.034s run time
transactions.test.ts:139:5 Captures request metadata
To view individual test run time comparison to the main branch, go to the Test Analytics Dashboard
🥹