📜 Description
SentryNetworkBody
Extract request/response bodies that are either JSON, formurlencoded, binary or text.
- Relies on having a
contentType to decide how to interpret the body (NSData).
- Relies on iOS's
UTType to decide whether something is JSON or text.
text:
tries .utf8 , then .isoLatin1 then gives up with BODY_PARSE_ERROR warning.
json:
tries JSONSerialization.jsonObject, gives up with BODY_PARSE_ERROR warning
UTType doesn't know:
extracts a placeholder body E.g. "[Body not captured: contentType=application/octet-stream (10240 bytes)]"
SentryReplayNetworkRequestOrResponse
- case-insensitive header extraction
💡 Motivation and Context
See first PR in stack.
💚 How did you test it?
Unit tests
make test-ios ONLY_TESTING="SentryReplayNetworkDetailsBodyTests,SentryReplayNetworkDetailsHeaderTests,SentryReplayNetworkDetailsIntegrationTests"
Test Suite 'SentryReplayNetworkDetailsBodyTests' started at 2026-03-19 15:25:09.315.
✔ testInit_withBinaryContentType_shouldCreateArtificialString (0.005 seconds)
✔ testInit_withEmptyData_shouldReturnNil (0.000 seconds)
✔ testInit_withFormURLEncoded_duplicateKeys_shouldPromoteToArray (0.001 seconds)
✔ testInit_withFormURLEncoded_emptyKeys_shouldBeSkipped (0.000 seconds)
✔ testInit_withFormURLEncoded_emptyValue_shouldParseAsEmptyString (0.000 seconds)
Resolving Package Graph
✔ testInit_withFormURLEncoded_equalsInValue_shouldPreserve (0.000 seconds)
✔ testInit_withFormURLEncoded_missingEquals_shouldFallbackToText (0.001 seconds)
✔ testInit_withFormURLEncoded_shouldParseAsForm (0.001 seconds)
✔ testInit_withInvalidJSON_shouldFallbackToString (0.001 seconds)
✔ testInit_withJSONArray_shouldParseCorrectly (0.000 seconds)
✔ testInit_withJSONDictionary_shouldParseCorrectly (0.001 seconds)
✔ testInit_withLargeData_shouldTruncate (0.005 seconds)
✔ testInit_withNilContentType_shouldCreatePlaceholder (0.000 seconds)
✔ testInit_withTextData_shouldStoreAsString (0.000 seconds)
✔ testInit_withUnrecognizedContentType_shouldCreatePlaceholder (0.000 seconds)
✔ testParseMimeAndEncoding_shouldHandleEdgeCases (0.001 seconds)
✔ testSerialize_withJSONArray_shouldReturnArray (0.001 seconds)
✔ testSerialize_withJSONDictionary_shouldReturnDictionary (0.001 seconds)
✔ testSerialize_withNoContentType_shouldCreatePlaceholder (0.001 seconds)
✔ testSerialize_withStringBody_shouldReturnDictionary (0.001 seconds)
Executed 20 tests, with 0 failures (0 unexpected) in 0.021 (0.041) seconds
Test Suite 'SentryTests.xctest' passed at 2026-03-19 15:25:09.356.
Executed 20 tests, with 0 failures (0 unexpected) in 0.021 (0.041) seconds
SentryReplayNetworkDetailsHeaderTests (4 tests):
testExtractHeaders_withNilInputs_returnsEmptyDict — nil headers/config returns empty
testExtractHeaders_unconfiguredHeadersAreExcluded — only configured headers are extracted
testExtractHeaders_caseInsensitiveMatching — header matching is case-insensitive
testExtractHeaders_nonStringValues_convertedToStrings — non-string header values are converted
SentryReplayNetworkDetailsIntegrationTests (4 tests):
testInit_withMethod_shouldSetMethod — HTTP method is stored
testSerialize_withFullData_shouldReturnCompleteDictionary — full detail serializes all fields
testSerialize_withPartialData_shouldOnlyIncludeSetFields — partial data omits unset fields
testSerialize_withHeaderFiltering_shouldOnlyIncludeConfiguredHeaders — header filtering works end-to-end
📝 Checklist
You have to check all boxes before merging:
Note
The pull request "feat(network-details): Implement header and body extraction" was created by @43jay but did not reference an issue. Therefore this issue was created for better visibility in external tools like Linear.
📜 Description
SentryNetworkBodyExtract request/response bodies that are either JSON, formurlencoded, binary or text.
contentTypeto decide how to interpret the body (NSData).UTTypeto decide whether something is JSON or text.text:
tries
.utf8, then.isoLatin1then gives up withBODY_PARSE_ERRORwarning.json:
tries
JSONSerialization.jsonObject, gives up withBODY_PARSE_ERRORwarningUTType doesn't know:
extracts a placeholder body E.g.
"[Body not captured: contentType=application/octet-stream (10240 bytes)]"SentryReplayNetworkRequestOrResponse💡 Motivation and Context
See first PR in stack.
💚 How did you test it?
Unit tests
make test-ios ONLY_TESTING="SentryReplayNetworkDetailsBodyTests,SentryReplayNetworkDetailsHeaderTests,SentryReplayNetworkDetailsIntegrationTests"Test Suite 'SentryReplayNetworkDetailsBodyTests' started at 2026-03-19 15:25:09.315.
✔ testInit_withBinaryContentType_shouldCreateArtificialString (0.005 seconds)
✔ testInit_withEmptyData_shouldReturnNil (0.000 seconds)
✔ testInit_withFormURLEncoded_duplicateKeys_shouldPromoteToArray (0.001 seconds)
✔ testInit_withFormURLEncoded_emptyKeys_shouldBeSkipped (0.000 seconds)
✔ testInit_withFormURLEncoded_emptyValue_shouldParseAsEmptyString (0.000 seconds)
Resolving Package Graph
✔ testInit_withFormURLEncoded_equalsInValue_shouldPreserve (0.000 seconds)
✔ testInit_withFormURLEncoded_missingEquals_shouldFallbackToText (0.001 seconds)
✔ testInit_withFormURLEncoded_shouldParseAsForm (0.001 seconds)
✔ testInit_withInvalidJSON_shouldFallbackToString (0.001 seconds)
✔ testInit_withJSONArray_shouldParseCorrectly (0.000 seconds)
✔ testInit_withJSONDictionary_shouldParseCorrectly (0.001 seconds)
✔ testInit_withLargeData_shouldTruncate (0.005 seconds)
✔ testInit_withNilContentType_shouldCreatePlaceholder (0.000 seconds)
✔ testInit_withTextData_shouldStoreAsString (0.000 seconds)
✔ testInit_withUnrecognizedContentType_shouldCreatePlaceholder (0.000 seconds)
✔ testParseMimeAndEncoding_shouldHandleEdgeCases (0.001 seconds)
✔ testSerialize_withJSONArray_shouldReturnArray (0.001 seconds)
✔ testSerialize_withJSONDictionary_shouldReturnDictionary (0.001 seconds)
✔ testSerialize_withNoContentType_shouldCreatePlaceholder (0.001 seconds)
✔ testSerialize_withStringBody_shouldReturnDictionary (0.001 seconds)
Executed 20 tests, with 0 failures (0 unexpected) in 0.021 (0.041) seconds
Test Suite 'SentryTests.xctest' passed at 2026-03-19 15:25:09.356.
Executed 20 tests, with 0 failures (0 unexpected) in 0.021 (0.041) seconds
SentryReplayNetworkDetailsHeaderTests (4 tests):
testExtractHeaders_withNilInputs_returnsEmptyDict— nil headers/config returns emptytestExtractHeaders_unconfiguredHeadersAreExcluded— only configured headers are extractedtestExtractHeaders_caseInsensitiveMatching— header matching is case-insensitivetestExtractHeaders_nonStringValues_convertedToStrings— non-string header values are convertedSentryReplayNetworkDetailsIntegrationTests (4 tests):
testInit_withMethod_shouldSetMethod— HTTP method is storedtestSerialize_withFullData_shouldReturnCompleteDictionary— full detail serializes all fieldstestSerialize_withPartialData_shouldOnlyIncludeSetFields— partial data omits unset fieldstestSerialize_withHeaderFiltering_shouldOnlyIncludeConfiguredHeaders— header filtering works end-to-end📝 Checklist
You have to check all boxes before merging:
sendDefaultPIIis enabled. N/A