Skip to content

Commit 8287b45

Browse files
authored
Merge a71499a into 91bb874
2 parents 91bb874 + a71499a commit 8287b45

File tree

8 files changed

+602
-187
lines changed

8 files changed

+602
-187
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
## Unreleased
44

5+
### Fixes
6+
7+
- Improve network body parsing and truncation handling ([#4958](https://github.com/getsentry/sentry-java/pull/4958))
8+
59
### Internal
610

711
- Support `metric` envelope item type ([#4956](https://github.com/getsentry/sentry-java/pull/4956))

sentry-android-replay/src/main/java/io/sentry/android/replay/DefaultReplayBreadcrumbConverter.kt

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,10 @@ public open class DefaultReplayBreadcrumbConverter() : ReplayBreadcrumbConverter
241241
networkData.request?.let { request ->
242242
val requestData = mutableMapOf<String, Any?>()
243243
request.size?.let { requestData["size"] = it }
244-
request.body?.let { requestData["body"] = it.value }
244+
request.body?.let {
245+
requestData["body"] = it.body
246+
requestData["warnings"] = it.warnings?.map { w -> w.value }
247+
}
245248

246249
if (request.headers.isNotEmpty()) {
247250
requestData["headers"] = request.headers
@@ -255,7 +258,10 @@ public open class DefaultReplayBreadcrumbConverter() : ReplayBreadcrumbConverter
255258
networkData.response?.let { response ->
256259
val responseData = mutableMapOf<String, Any?>()
257260
response.size?.let { responseData["size"] = it }
258-
response.body?.let { responseData["body"] = it.value }
261+
response.body?.let {
262+
responseData["body"] = it.body
263+
responseData["warnings"] = it.warnings?.map { w -> w.value }
264+
}
259265

260266
if (response.headers.isNotEmpty()) {
261267
responseData["headers"] = response.headers

sentry-android-replay/src/test/java/io/sentry/android/replay/DefaultReplayBreadcrumbConverterTest.kt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -423,15 +423,15 @@ class DefaultReplayBreadcrumbConverterTest {
423423
fakeOkHttpNetworkDetails.setRequestDetails(
424424
ReplayNetworkRequestOrResponse(
425425
100L,
426-
NetworkBody.fromString("request body content"),
426+
NetworkBody("request body content"),
427427
mapOf("Content-Type" to "application/json"),
428428
)
429429
)
430430
fakeOkHttpNetworkDetails.setResponseDetails(
431431
200,
432432
ReplayNetworkRequestOrResponse(
433433
500L,
434-
NetworkBody.fromJsonObject(mapOf("status" to "success", "message" to "OK")),
434+
NetworkBody(mapOf("status" to "success", "message" to "OK")),
435435
mapOf("Content-Type" to "text/plain"),
436436
),
437437
)
@@ -485,15 +485,15 @@ class DefaultReplayBreadcrumbConverterTest {
485485
fakeOkHttpNetworkDetails.setRequestDetails(
486486
ReplayNetworkRequestOrResponse(
487487
150L,
488-
NetworkBody.fromJsonArray(listOf("item1", "item2", "item3")),
488+
NetworkBody(listOf("item1", "item2", "item3")),
489489
mapOf("Content-Type" to "application/json"),
490490
)
491491
)
492492
fakeOkHttpNetworkDetails.setResponseDetails(
493493
404,
494494
ReplayNetworkRequestOrResponse(
495495
550L,
496-
NetworkBody.fromJsonObject(mapOf("status" to "success", "message" to "OK")),
496+
NetworkBody(mapOf("status" to "success", "message" to "OK")),
497497
mapOf("Content-Type" to "text/plain"),
498498
),
499499
)
@@ -540,15 +540,15 @@ class DefaultReplayBreadcrumbConverterTest {
540540
networkRequestData.setRequestDetails(
541541
ReplayNetworkRequestOrResponse(
542542
100L,
543-
NetworkBody.fromString("request body content"),
543+
NetworkBody("request body content"),
544544
mapOf("Content-Type" to "application/json"),
545545
)
546546
)
547547
networkRequestData.setResponseDetails(
548548
200,
549549
ReplayNetworkRequestOrResponse(
550550
100L,
551-
NetworkBody.fromString("respnse body content"),
551+
NetworkBody("response body content"),
552552
mapOf("Content-Type" to "application/json"),
553553
),
554554
)

sentry-okhttp/src/main/java/io/sentry/okhttp/SentryOkHttpInterceptor.kt

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -317,11 +317,6 @@ public open class SentryOkHttpInterceptor(
317317
val contentTypeString = contentType?.toString()
318318
val maxBodySize = SentryReplayOptions.MAX_NETWORK_BODY_SIZE
319319

320-
val contentLength = responseBody.contentLength()
321-
if (contentLength > maxBodySize * 2) {
322-
return NetworkBody.fromString("[Response body too large: $contentLength bytes]")
323-
}
324-
325320
// Peek at the body (doesn't consume it)
326321
val peekBody = peekBody(maxBodySize.toLong())
327322
val bodyBytes = peekBody.bytes()

sentry/api/sentry.api

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7481,29 +7481,22 @@ public final class io/sentry/util/UrlUtils$UrlDetails {
74817481
public fun getUrlOrFallback ()Ljava/lang/String;
74827482
}
74837483

7484-
public abstract interface class io/sentry/util/network/NetworkBody {
7485-
public static fun fromJsonArray (Ljava/util/List;)Lio/sentry/util/network/NetworkBody;
7486-
public static fun fromJsonObject (Ljava/util/Map;)Lio/sentry/util/network/NetworkBody;
7487-
public static fun fromString (Ljava/lang/String;)Lio/sentry/util/network/NetworkBody;
7488-
public abstract fun getValue ()Ljava/lang/Object;
7489-
}
7490-
7491-
public final class io/sentry/util/network/NetworkBody$JsonArrayImpl : io/sentry/util/network/NetworkBody {
7492-
public synthetic fun getValue ()Ljava/lang/Object;
7493-
public fun getValue ()Ljava/util/List;
7494-
public fun toString ()Ljava/lang/String;
7495-
}
7496-
7497-
public final class io/sentry/util/network/NetworkBody$JsonObjectImpl : io/sentry/util/network/NetworkBody {
7498-
public synthetic fun getValue ()Ljava/lang/Object;
7499-
public fun getValue ()Ljava/util/Map;
7484+
public final class io/sentry/util/network/NetworkBody {
7485+
public fun <init> (Ljava/lang/Object;)V
7486+
public fun <init> (Ljava/lang/Object;Ljava/util/List;)V
7487+
public fun getBody ()Ljava/lang/Object;
7488+
public fun getWarnings ()Ljava/util/List;
75007489
public fun toString ()Ljava/lang/String;
75017490
}
75027491

7503-
public final class io/sentry/util/network/NetworkBody$StringBodyImpl : io/sentry/util/network/NetworkBody {
7504-
public synthetic fun getValue ()Ljava/lang/Object;
7492+
public final class io/sentry/util/network/NetworkBody$NetworkBodyWarning : java/lang/Enum {
7493+
public static final field BODY_PARSE_ERROR Lio/sentry/util/network/NetworkBody$NetworkBodyWarning;
7494+
public static final field INVALID_JSON Lio/sentry/util/network/NetworkBody$NetworkBodyWarning;
7495+
public static final field JSON_TRUNCATED Lio/sentry/util/network/NetworkBody$NetworkBodyWarning;
7496+
public static final field TEXT_TRUNCATED Lio/sentry/util/network/NetworkBody$NetworkBodyWarning;
75057497
public fun getValue ()Ljava/lang/String;
7506-
public fun toString ()Ljava/lang/String;
7498+
public static fun valueOf (Ljava/lang/String;)Lio/sentry/util/network/NetworkBody$NetworkBodyWarning;
7499+
public static fun values ()[Lio/sentry/util/network/NetworkBody$NetworkBodyWarning;
75077500
}
75087501

75097502
public final class io/sentry/util/network/NetworkBodyParser {
Lines changed: 32 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -1,113 +1,61 @@
11
package io.sentry.util.network;
22

33
import java.util.List;
4-
import java.util.Map;
5-
import org.jetbrains.annotations.NotNull;
4+
import org.jetbrains.annotations.ApiStatus;
5+
import org.jetbrains.annotations.Nullable;
66

77
/**
8-
* Represents the body content of a network request or response. Can be one of: JSON object, JSON
9-
* array, or string.
8+
* Represents the body content of a network request or response.
109
*
1110
* <p>See <a
1211
* href="https://github.com/getsentry/sentry-javascript/blob/develop/packages/replay-internal/src/types/request.ts">Javascript
1312
* types</a>
1413
*/
15-
public interface NetworkBody {
14+
@ApiStatus.Internal
15+
public final class NetworkBody {
1616

17-
/**
18-
* Creates a NetworkBody from a JSON object.
19-
*
20-
* @param value The map representing the JSON object
21-
* @return A NetworkBody instance for the JSON object
22-
*/
23-
static @NotNull NetworkBody fromJsonObject(@NotNull final Map<String, Object> value) {
24-
return new JsonObjectImpl(value);
25-
}
17+
private final @Nullable Object body;
18+
private final @Nullable List<NetworkBodyWarning> warnings;
2619

27-
/**
28-
* Creates a NetworkBody from a JSON array.
29-
*
30-
* @param value The list representing the JSON array
31-
* @return A NetworkBody instance for the JSON array
32-
*/
33-
static @NotNull NetworkBody fromJsonArray(@NotNull final List<Object> value) {
34-
return new JsonArrayImpl(value);
20+
public NetworkBody(final @Nullable Object body) {
21+
this(body, null);
3522
}
3623

37-
/**
38-
* Creates a NetworkBody from string content.
39-
*
40-
* @param value The string content
41-
* @return A NetworkBody instance for the string
42-
*/
43-
static @NotNull NetworkBody fromString(@NotNull final String value) {
44-
return new StringBodyImpl(value);
24+
public NetworkBody(
25+
final @Nullable Object body, final @Nullable List<NetworkBodyWarning> warnings) {
26+
this.body = body;
27+
this.warnings = warnings;
4528
}
4629

47-
/**
48-
* Gets the underlying value of this NetworkBody.
49-
*
50-
* @return The value as an Object (could be Map, List, or String)
51-
*/
52-
@NotNull
53-
Object getValue();
54-
55-
// Private implementation classes
56-
57-
/** Implementation for JSON object bodies */
58-
final class JsonObjectImpl implements NetworkBody {
59-
private final @NotNull Map<String, Object> value;
60-
61-
JsonObjectImpl(@NotNull final Map<String, Object> value) {
62-
this.value = value;
63-
}
64-
65-
@Override
66-
public @NotNull Map<String, Object> getValue() {
67-
return value;
68-
}
69-
70-
@Override
71-
public String toString() {
72-
return "NetworkBody.JsonObject{" + value + '}';
73-
}
30+
public @Nullable Object getBody() {
31+
return body;
7432
}
7533

76-
/** Implementation for JSON array bodies */
77-
final class JsonArrayImpl implements NetworkBody {
78-
private final @NotNull List<Object> value;
79-
80-
JsonArrayImpl(@NotNull final List<Object> value) {
81-
this.value = value;
82-
}
83-
84-
@Override
85-
public @NotNull List<Object> getValue() {
86-
return value;
87-
}
88-
89-
@Override
90-
public String toString() {
91-
return "NetworkBody.JsonArray{" + value + '}';
92-
}
34+
public @Nullable List<NetworkBodyWarning> getWarnings() {
35+
return warnings;
9336
}
9437

95-
/** Implementation for string bodies */
96-
final class StringBodyImpl implements NetworkBody {
97-
private final @NotNull String value;
38+
// Based on
39+
// https://github.com/getsentry/sentry/blob/ccb61aa9b0f33e1333830093a5ce3bd5db88ef33/static/app/utils/replays/replay.tsx#L5-L12
40+
public enum NetworkBodyWarning {
41+
JSON_TRUNCATED("JSON_TRUNCATED"),
42+
TEXT_TRUNCATED("TEXT_TRUNCATED"),
43+
INVALID_JSON("INVALID_JSON"),
44+
BODY_PARSE_ERROR("BODY_PARSE_ERROR");
45+
46+
private final String value;
9847

99-
StringBodyImpl(@NotNull final String value) {
48+
NetworkBodyWarning(String value) {
10049
this.value = value;
10150
}
10251

103-
@Override
104-
public @NotNull String getValue() {
52+
public String getValue() {
10553
return value;
10654
}
55+
}
10756

108-
@Override
109-
public String toString() {
110-
return "NetworkBody.StringBody{" + value + '}';
111-
}
57+
@Override
58+
public String toString() {
59+
return "NetworkBody{" + "body=" + body + ", warnings=" + warnings + '}';
11260
}
11361
}

0 commit comments

Comments
 (0)