@@ -8,6 +8,7 @@ import { beforeAll, beforeEach, describe, expect, onTestFinished, test, vi } fro
88import { setAsyncLocalStorageAsyncContextStrategy } from '../src/async' ;
99import type { CloudflareOptions } from '../src/client' ;
1010import { CloudflareClient } from '../src/client' ;
11+ import { httpServerIntegration } from '../src/integrations/httpServer' ;
1112import { wrapRequestHandler } from '../src/request' ;
1213
1314const MOCK_OPTIONS : CloudflareOptions = {
@@ -206,18 +207,14 @@ describe('withSentry', () => {
206207 expect ( sentryEvent . contexts ?. culture ) . toEqual ( { timezone : 'UTC' } ) ;
207208 } ) ;
208209
209- // TODO(v11): Body capture should be gated on `dataCollection.httpBodies` (only capture when
210- // `'incomingRequest'` is listed). Until then we keep the historical behavior of capturing
211- // incoming request bodies by default at `'medium'`, consistent with the Node SDK.
212- test ( 'captures request body with default integration (medium size)' , async ( ) => {
210+ test ( 'captures request body by default (all body types included by default)' , async ( ) => {
213211 let sentryEvent : Event = { } ;
214212 const context = createMockExecutionContext ( ) ;
215213
216214 await wrapRequestHandler (
217215 {
218216 options : {
219217 ...MOCK_OPTIONS ,
220- // Default integrations include httpServerIntegration with 'medium' default
221218 beforeSend ( event ) {
222219 sentryEvent = event ;
223220 return null ;
@@ -241,6 +238,69 @@ describe('withSentry', () => {
241238 ) ;
242239 } ) ;
243240
241+ test ( 'does not capture request body when dataCollection.httpBodies excludes incomingRequest' , async ( ) => {
242+ let sentryEvent : Event = { } ;
243+ const context = createMockExecutionContext ( ) ;
244+
245+ await wrapRequestHandler (
246+ {
247+ options : {
248+ ...MOCK_OPTIONS ,
249+ dataCollection : { httpBodies : [ ] } ,
250+ beforeSend ( event ) {
251+ sentryEvent = event ;
252+ return null ;
253+ } ,
254+ } ,
255+ request : new Request ( 'https://example.com' , {
256+ method : 'POST' ,
257+ headers : { 'content-type' : 'application/json' } ,
258+ body : JSON . stringify ( { username : 'test' , data : 'value' } ) ,
259+ } ) ,
260+ context,
261+ } ,
262+ ( ) => {
263+ SentryCore . captureMessage ( 'request body' ) ;
264+ return new Response ( 'test' ) ;
265+ } ,
266+ ) ;
267+
268+ expect ( sentryEvent . sdkProcessingMetadata ?. normalizedRequest ?. data ) . toBeUndefined ( ) ;
269+ } ) ;
270+
271+ test ( 'explicit maxRequestBodySize overrides dataCollection.httpBodies' , async ( ) => {
272+ let sentryEvent : Event = { } ;
273+ const context = createMockExecutionContext ( ) ;
274+
275+ await wrapRequestHandler (
276+ {
277+ options : {
278+ ...MOCK_OPTIONS ,
279+ integrations : [
280+ // httpBodies not set → would default to 'none', but explicit override wins
281+ httpServerIntegration ( { maxRequestBodySize : 'medium' } ) ,
282+ ] ,
283+ beforeSend ( event ) {
284+ sentryEvent = event ;
285+ return null ;
286+ } ,
287+ } ,
288+ request : new Request ( 'https://example.com' , {
289+ method : 'POST' ,
290+ headers : { 'content-type' : 'application/json' } ,
291+ body : JSON . stringify ( { key : 'value' } ) ,
292+ } ) ,
293+ context,
294+ } ,
295+ ( ) => {
296+ SentryCore . captureMessage ( 'request body' ) ;
297+ return new Response ( 'test' ) ;
298+ } ,
299+ ) ;
300+
301+ expect ( sentryEvent . sdkProcessingMetadata ?. normalizedRequest ?. data ) . toEqual ( JSON . stringify ( { key : 'value' } ) ) ;
302+ } ) ;
303+
244304 // TODO(v11): Cookies should be attached (subject to denylist filtering) by default. Until then we keep the
245305 // historical Cloudflare behavior of not attaching cookies unless the user explicitly opts in.
246306 test ( 'does not capture cookies by default' , async ( ) => {
0 commit comments