Skip to content

Commit 56a29f9

Browse files
authored
Merge pull request #2380 from bugsnag/release/v6.23.0
release v6.23.0
2 parents 66136b0 + d6fac65 commit 56a29f9

64 files changed

Lines changed: 3638 additions & 82 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/codeql.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,12 @@ jobs:
4444

4545
steps:
4646
- name: Checkout repository
47-
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 #v6.0.1
47+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2
4848
with:
4949
submodules: recursive
5050
- uses: gradle/actions/wrapper-validation@4d9f0ba0025fe599b4ebab900eb7f3a1d93ef4c2 #v5.0.0
5151

52-
- uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e #v5.1.0
52+
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 #v5.2.0
5353
with:
5454
distribution: 'zulu'
5555
java-version: 17
@@ -64,7 +64,7 @@ jobs:
6464

6565
# Initializes the CodeQL tools for scanning.
6666
- name: Initialize CodeQL
67-
uses: github/codeql-action/init@cdefb33c0f6224e58673d9004f47f7cb3e328b89 #v4.31.10
67+
uses: github/codeql-action/init@b20883b0cd1f46c72ae0ba6d1090936928f9fa30 #v4.32.0
6868
with:
6969
languages: ${{ matrix.language }}
7070
# If you wish to specify custom queries, you can do so here or in a config file.
@@ -83,6 +83,6 @@ jobs:
8383
./gradlew --no-daemon assemble
8484
8585
- name: Perform CodeQL Analysis
86-
uses: github/codeql-action/analyze@cdefb33c0f6224e58673d9004f47f7cb3e328b89 #v4.31.10
86+
uses: github/codeql-action/analyze@b20883b0cd1f46c72ae0ba6d1090936928f9fa30 #v4.32.0
8787
with:
8888
category: "/language:${{matrix.language}}"

.github/workflows/scorecard.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ jobs:
3232

3333
steps:
3434
- name: "Checkout code"
35-
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
35+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
3636
with:
3737
persist-credentials: false
3838

@@ -68,13 +68,13 @@ jobs:
6868
# Upload the results to GitHub's code scanning dashboard (optional).
6969
# Commenting out will disable upload of results to your repo's Code Scanning dashboard
7070
- name: "Upload to code-scanning"
71-
uses: github/codeql-action/upload-sarif@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v4.31.10
71+
uses: github/codeql-action/upload-sarif@b20883b0cd1f46c72ae0ba6d1090936928f9fa30 # v4.32.0
7272
with:
7373
sarif_file: results.sarif
7474

7575
gradle-wrapper-validation:
7676
name: "Checksum validation of Gradle Wrappers"
7777
runs-on: ubuntu-latest
7878
steps:
79-
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
79+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
8080
- uses: gradle/actions/wrapper-validation@4d9f0ba0025fe599b4ebab900eb7f3a1d93ef4c2 # v5.0.0

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# Changelog
22

3+
## 6.23.0 (2026-02-02)
4+
5+
### Enhancements
6+
7+
* Introduced new OkHttp Interceptor based instrumentation for HTTP errors and breadcrumbs
8+
[#2371](https://github.com/bugsnag/bugsnag-android/pull/2371)
9+
310
## 6.22.0 (2026-01-19)
411

512
### Enhancements

CODEOWNERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
bugsnag-android/ @lemnik @YYChen01988
22
bugsnag-android-core/ @lemnik @YYChen01988
3+
bugsnag-android-http-api/ @lemnik @YYChen01988
34
bugsnag-plugin-android-anr/ @lemnik @YYChen01988
45
bugsnag-plugin-android-apphang/ @lemnik @YYChen01988
56
bugsnag-plugin-android-exitinfo/ @lemnik @YYChen01988

bugsnag-android-core/api/bugsnag-android-core.api

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
public abstract class com/bugsnag/android/AbstractHttpEntity {
2+
protected final field headers Ljava/util/Map;
3+
public fun addHeader (Ljava/lang/String;Ljava/lang/String;)V
4+
public fun getBody ()Ljava/lang/String;
5+
public fun getBodyLength ()J
6+
public fun getHeader (Ljava/lang/String;)Ljava/lang/String;
7+
public fun getHeaderNames ()Ljava/util/Set;
8+
public fun removeHeader (Ljava/lang/String;)V
9+
public fun setBody (Ljava/lang/String;)V
10+
public fun setBodyLength (J)V
11+
}
12+
113
public class com/bugsnag/android/App : com/bugsnag/android/JsonStream$Streamable {
214
public final fun getBinaryArch ()Ljava/lang/String;
315
public final fun getBuildUuid ()Ljava/lang/String;
@@ -459,6 +471,8 @@ public class com/bugsnag/android/Event : com/bugsnag/android/FeatureFlagAware, c
459471
public fun getMetadata (Ljava/lang/String;)Ljava/util/Map;
460472
public fun getMetadata (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;
461473
public fun getOriginalError ()Ljava/lang/Throwable;
474+
public fun getRequest ()Lcom/bugsnag/android/Request;
475+
public fun getResponse ()Lcom/bugsnag/android/Response;
462476
public fun getSeverity ()Lcom/bugsnag/android/Severity;
463477
public fun getThreads ()Ljava/util/List;
464478
public fun getUser ()Lcom/bugsnag/android/User;
@@ -472,6 +486,8 @@ public class com/bugsnag/android/Event : com/bugsnag/android/FeatureFlagAware, c
472486
public fun setErrorReportingThread (Lcom/bugsnag/android/Thread;)V
473487
public fun setGroupingDiscriminator (Ljava/lang/String;)Ljava/lang/String;
474488
public fun setGroupingHash (Ljava/lang/String;)V
489+
public fun setRequest (Lcom/bugsnag/android/Request;)V
490+
public fun setResponse (Lcom/bugsnag/android/Response;)V
475491
public fun setSeverity (Lcom/bugsnag/android/Severity;)V
476492
public fun setTraceCorrelation (Ljava/util/UUID;J)V
477493
public fun setUnhandled (Z)V
@@ -689,6 +705,29 @@ public abstract interface class com/bugsnag/android/Plugin {
689705
public abstract fun unload ()V
690706
}
691707

708+
public final class com/bugsnag/android/Request : com/bugsnag/android/AbstractHttpEntity, com/bugsnag/android/JsonStream$Streamable {
709+
public fun <init> (Ljava/lang/String;Ljava/lang/String;)V
710+
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
711+
public fun addQueryParameter (Ljava/lang/String;Ljava/lang/String;)V
712+
public fun getHttpMethod ()Ljava/lang/String;
713+
public fun getHttpVersion ()Ljava/lang/String;
714+
public fun getQueryParameter (Ljava/lang/String;)Ljava/lang/String;
715+
public fun getQueryParameterNames ()Ljava/util/Set;
716+
public fun getUrl ()Ljava/lang/String;
717+
public fun removeQueryParameter (Ljava/lang/String;)V
718+
public fun setHttpMethod (Ljava/lang/String;)V
719+
public fun setHttpVersion (Ljava/lang/String;)V
720+
public fun setUrl (Ljava/lang/String;)V
721+
public fun toStream (Lcom/bugsnag/android/JsonStream;)V
722+
}
723+
724+
public final class com/bugsnag/android/Response : com/bugsnag/android/AbstractHttpEntity, com/bugsnag/android/JsonStream$Streamable {
725+
public fun <init> (I)V
726+
public fun getStatusCode ()I
727+
public fun setStatusCode (I)V
728+
public fun toStream (Lcom/bugsnag/android/JsonStream;)V
729+
}
730+
692731
public final class com/bugsnag/android/Session : com/bugsnag/android/Deliverable, com/bugsnag/android/JsonStream$Streamable, com/bugsnag/android/UserAware {
693732
public fun getApiKey ()Ljava/lang/String;
694733
public fun getApp ()Lcom/bugsnag/android/App;
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
package com.bugsnag.android
2+
3+
import org.junit.Assert.assertEquals
4+
import org.junit.Assert.assertNull
5+
import org.junit.Test
6+
7+
class RequestTest {
8+
private val testBodyString = "this is a body string with some content"
9+
private val customBodyLength = 5000L
10+
11+
@Test
12+
fun urlQueryIsExtracted() {
13+
val request = Request(
14+
"1.1",
15+
"GET",
16+
"http://localhost/test?t1=arg1&test2=argument+2"
17+
)
18+
19+
assertEquals("http://localhost/test", request.url)
20+
assertEquals("arg1", request.getQueryParameter("t1"))
21+
assertEquals("argument 2", request.getQueryParameter("test2"))
22+
assertEquals(setOf("t1", "test2"), request.queryParameterNames)
23+
}
24+
25+
@Test
26+
fun setBody() {
27+
val request = Request("1.1", "GET", "http://localhost/")
28+
request.body = testBodyString
29+
assertEquals(testBodyString, request.body)
30+
}
31+
32+
@Test
33+
fun setBodyWithUserLength() {
34+
val request = Request("1.1", "GET", "http://localhost/")
35+
request.bodyLength = customBodyLength
36+
request.body = testBodyString
37+
38+
assertEquals(testBodyString, request.body)
39+
assertEquals(customBodyLength, request.bodyLength)
40+
}
41+
42+
@Test
43+
fun setNullBody() {
44+
val request = Request("1.1", "GET", "http://localhost/")
45+
request.body = testBodyString
46+
request.body = null
47+
assertNull(request.body)
48+
}
49+
50+
@Test
51+
fun setHttpMethod() {
52+
val request = Request("1.1", "GET", "http://localhost/")
53+
assertEquals("GET", request.httpMethod)
54+
55+
request.httpMethod = "POST"
56+
assertEquals("POST", request.httpMethod)
57+
}
58+
59+
@Test
60+
fun setHttpVersion() {
61+
val request = Request("1.1", "1.1", "http://localhost/")
62+
assertEquals("1.1", request.httpVersion)
63+
64+
request.httpVersion = "1.0"
65+
assertEquals("1.0", request.httpVersion)
66+
}
67+
68+
@Test
69+
fun setUrl() {
70+
val request = Request("1.1", "GET", "http://localhost/")
71+
assertEquals("http://localhost/", request.url)
72+
73+
request.url = "https://google.com"
74+
assertEquals("https://google.com", request.url)
75+
}
76+
77+
@Test
78+
fun setUrlWithQuery() {
79+
val request = Request("1.1", "GET", "http://localhost/")
80+
request.url = "http://foo.com?a=1&b=2"
81+
assertEquals("http://foo.com", request.url)
82+
assertEquals("1", request.getQueryParameter("a"))
83+
assertEquals("2", request.getQueryParameter("b"))
84+
assertEquals(setOf("a", "b"), request.queryParameterNames)
85+
}
86+
87+
@Test
88+
fun queryParameters() {
89+
val request = Request("1.1", "GET", "http://localhost/")
90+
request.addQueryParameter("foo", "bar")
91+
request.addQueryParameter("another", "param")
92+
93+
assertEquals("bar", request.getQueryParameter("foo"))
94+
assertEquals("param", request.getQueryParameter("another"))
95+
assertEquals(setOf("foo", "another"), request.queryParameterNames)
96+
97+
request.removeQueryParameter("foo")
98+
assertNull(request.getQueryParameter("foo"))
99+
assertEquals(setOf("another"), request.queryParameterNames)
100+
}
101+
102+
@Test
103+
fun headers() {
104+
val request = Request("1.1", "GET", "http://localhost/")
105+
request.addHeader("X-Test", "value")
106+
request.addHeader("Another-Header", "another-value")
107+
108+
assertEquals("value", request.getHeader("X-Test"))
109+
assertEquals("another-value", request.getHeader("Another-Header"))
110+
assertEquals(setOf("X-Test", "Another-Header"), request.headerNames)
111+
112+
request.removeHeader("X-Test")
113+
assertEquals("", request.getHeader("X-Test"))
114+
assertEquals(setOf("Another-Header"), request.headerNames)
115+
}
116+
117+
@Test
118+
fun setBodyLength() {
119+
val request = Request("1.1", "GET", "http://localhost/")
120+
request.bodyLength = 1234
121+
assertEquals(1234, request.bodyLength)
122+
123+
// test negative value is ignored
124+
request.bodyLength = -5
125+
assertEquals(1234, request.bodyLength)
126+
}
127+
}
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
package com.bugsnag.android;
2+
3+
import androidx.annotation.IntRange;
4+
import androidx.annotation.NonNull;
5+
import androidx.annotation.Nullable;
6+
7+
import java.util.Collections;
8+
import java.util.LinkedHashMap;
9+
import java.util.Map;
10+
import java.util.Set;
11+
12+
@SuppressWarnings("ConstantValue")
13+
public abstract class AbstractHttpEntity {
14+
protected final Map<String, String> headers = new LinkedHashMap<>();
15+
16+
@Nullable
17+
private String body;
18+
private long bodyLength = -1L;
19+
20+
// package-protected constructor
21+
AbstractHttpEntity() {
22+
}
23+
24+
/**
25+
* Add a header to this reported HTTP entity.
26+
*
27+
* @param name the name of the header
28+
* @param value the value of the header
29+
*/
30+
public void addHeader(@NonNull String name, @NonNull String value) {
31+
if (name == null || value == null) {
32+
return;
33+
}
34+
35+
headers.put(name, value);
36+
}
37+
38+
/**
39+
* Remove the specified header by name (case-sensitive).
40+
*
41+
* @param name the header to remove
42+
*/
43+
public void removeHeader(@NonNull String name) {
44+
headers.remove(name);
45+
}
46+
47+
/**
48+
* Return the headers that are set for this HTTP entity.
49+
*
50+
* @return the header names
51+
*/
52+
@NonNull
53+
public Set<String> getHeaderNames() {
54+
return Collections.unmodifiableSet(headers.keySet());
55+
}
56+
57+
/**
58+
* Return the HTTP header by name or an empty string if the header is not present.
59+
*
60+
* @param headerName the header name (case-sensitive)
61+
* @return the value of the header or an empty string
62+
*/
63+
@NonNull
64+
public String getHeader(@NonNull String headerName) {
65+
if (headerName == null) {
66+
return "";
67+
}
68+
69+
String headerValue = headers.get(headerName);
70+
return headerValue != null ? headerValue : "";
71+
}
72+
73+
/**
74+
* Return the captured HTTP body if one has been set, or null.
75+
*
76+
* @return the captured HTTP body
77+
*/
78+
@Nullable
79+
public String getBody() {
80+
return body;
81+
}
82+
83+
/**
84+
* Set or clear the captured body.
85+
*
86+
* @param body the body to report
87+
*/
88+
public void setBody(@Nullable String body) {
89+
this.body = body;
90+
}
91+
92+
/**
93+
* Return the body length (as set with {@link #setBodyLength(long)}) or -1 if none has been set.
94+
*
95+
* @return the number of bytes in the body
96+
*/
97+
public long getBodyLength() {
98+
return bodyLength;
99+
}
100+
101+
/**
102+
* Change the reported size of the request body size (in bytes).
103+
*
104+
* @param bodyLength the number of bytes in the request body
105+
*/
106+
public void setBodyLength(@IntRange(from = 0L) long bodyLength) {
107+
if (bodyLength >= 0) {
108+
this.bodyLength = bodyLength;
109+
}
110+
}
111+
}

0 commit comments

Comments
 (0)