Skip to content

Commit a0ae84b

Browse files
committed
feat(http): added Request/Response as optional properties on an Event
1 parent 57279d8 commit a0ae84b

File tree

8 files changed

+646
-47
lines changed

8 files changed

+646
-47
lines changed

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

Lines changed: 36 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;
@@ -411,6 +423,8 @@ public class com/bugsnag/android/Event : com/bugsnag/android/FeatureFlagAware, c
411423
public fun getMetadata (Ljava/lang/String;)Ljava/util/Map;
412424
public fun getMetadata (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;
413425
public fun getOriginalError ()Ljava/lang/Throwable;
426+
public fun getRequest ()Lcom/bugsnag/android/Request;
427+
public fun getResponse ()Lcom/bugsnag/android/Response;
414428
public fun getSeverity ()Lcom/bugsnag/android/Severity;
415429
public fun getThreads ()Ljava/util/List;
416430
public fun getUser ()Lcom/bugsnag/android/User;
@@ -424,6 +438,8 @@ public class com/bugsnag/android/Event : com/bugsnag/android/FeatureFlagAware, c
424438
public fun setErrorReportingThread (Lcom/bugsnag/android/Thread;)V
425439
public fun setGroupingDiscriminator (Ljava/lang/String;)Ljava/lang/String;
426440
public fun setGroupingHash (Ljava/lang/String;)V
441+
public fun setRequest (Lcom/bugsnag/android/Request;)V
442+
public fun setResponse (Lcom/bugsnag/android/Response;)V
427443
public fun setSeverity (Lcom/bugsnag/android/Severity;)V
428444
public fun setTraceCorrelation (Ljava/util/UUID;J)V
429445
public fun setUnhandled (Z)V
@@ -641,6 +657,26 @@ public abstract interface class com/bugsnag/android/Plugin {
641657
public abstract fun unload ()V
642658
}
643659

660+
public final class com/bugsnag/android/Request : com/bugsnag/android/AbstractHttpEntity, com/bugsnag/android/JsonStream$Streamable {
661+
public fun addQueryParameter (Ljava/lang/String;Ljava/lang/String;)V
662+
public fun getHttpMethod ()Ljava/lang/String;
663+
public fun getHttpVersion ()Ljava/lang/String;
664+
public fun getQueryParameter (Ljava/lang/String;)Ljava/lang/String;
665+
public fun getQueryParameterNames ()Ljava/util/Set;
666+
public fun getUrl ()Ljava/lang/String;
667+
public fun removeQueryParameter (Ljava/lang/String;)V
668+
public fun setHttpMethod (Ljava/lang/String;)V
669+
public fun setHttpVersion (Ljava/lang/String;)V
670+
public fun setUrl (Ljava/lang/String;)V
671+
public fun toStream (Lcom/bugsnag/android/JsonStream;)V
672+
}
673+
674+
public final class com/bugsnag/android/Response : com/bugsnag/android/AbstractHttpEntity, com/bugsnag/android/JsonStream$Streamable {
675+
public fun getStatusCode ()I
676+
public fun setStatusCode (I)V
677+
public fun toStream (Lcom/bugsnag/android/JsonStream;)V
678+
}
679+
644680
public final class com/bugsnag/android/Session : com/bugsnag/android/Deliverable, com/bugsnag/android/JsonStream$Streamable, com/bugsnag/android/UserAware {
645681
public fun getApiKey ()Ljava/lang/String;
646682
public fun getApp ()Lcom/bugsnag/android/App;
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
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+
private val logger = NoopLogger
12+
13+
@Test
14+
fun urlQueryIsExtracted() {
15+
val request = Request(
16+
logger,
17+
"GET",
18+
"1.1",
19+
"http://localhost/test?t1=arg1&test2=argument+2"
20+
)
21+
22+
assertEquals("http://localhost/test", request.url)
23+
assertEquals("arg1", request.getQueryParameter("t1"))
24+
assertEquals("argument 2", request.getQueryParameter("test2"))
25+
assertEquals(setOf("t1", "test2"), request.queryParameterNames)
26+
}
27+
28+
@Test
29+
fun setBody() {
30+
val request = Request(logger, "GET", "1.1", "http://localhost/")
31+
request.body = testBodyString
32+
assertEquals(testBodyString, request.body)
33+
}
34+
35+
@Test
36+
fun setBodyWithUserLength() {
37+
val request = Request(logger, "GET", "1.1", "http://localhost/")
38+
request.bodyLength = customBodyLength
39+
request.body = testBodyString
40+
41+
assertEquals(testBodyString, request.body)
42+
assertEquals(customBodyLength, request.bodyLength)
43+
}
44+
45+
@Test
46+
fun setNullBody() {
47+
val request = Request(logger, "GET", "1.1", "http://localhost/")
48+
request.body = testBodyString
49+
request.body = null
50+
assertNull(request.body)
51+
}
52+
53+
@Test
54+
fun setHttpMethod() {
55+
val request = Request(logger, "GET", "1.1", "http://localhost/")
56+
assertEquals("GET", request.httpMethod)
57+
58+
request.httpMethod = "POST"
59+
assertEquals("POST", request.httpMethod)
60+
}
61+
62+
@Test
63+
fun setHttpVersion() {
64+
val request = Request(logger, "1.1", "1.1", "http://localhost/")
65+
assertEquals("1.1", request.httpVersion)
66+
67+
request.httpVersion = "1.0"
68+
assertEquals("1.0", request.httpVersion)
69+
}
70+
71+
@Test
72+
fun setUrl() {
73+
val request = Request(logger, "GET", "1.1", "http://localhost/")
74+
assertEquals("http://localhost/", request.url)
75+
76+
request.url = "https://google.com"
77+
assertEquals("https://google.com", request.url)
78+
}
79+
80+
@Test
81+
fun setUrlWithQuery() {
82+
val request = Request(logger, "GET", "1.1", "http://localhost/")
83+
request.url = "http://foo.com?a=1&b=2"
84+
assertEquals("http://foo.com", request.url)
85+
assertEquals("1", request.getQueryParameter("a"))
86+
assertEquals("2", request.getQueryParameter("b"))
87+
assertEquals(setOf("a", "b"), request.queryParameterNames)
88+
}
89+
90+
@Test
91+
fun queryParameters() {
92+
val request = Request(logger, "GET", "1.1", "http://localhost/")
93+
request.addQueryParameter("foo", "bar")
94+
request.addQueryParameter("another", "param")
95+
96+
assertEquals("bar", request.getQueryParameter("foo"))
97+
assertEquals("param", request.getQueryParameter("another"))
98+
assertEquals(setOf("foo", "another"), request.queryParameterNames)
99+
100+
request.removeQueryParameter("foo")
101+
assertNull(request.getQueryParameter("foo"))
102+
assertEquals(setOf("another"), request.queryParameterNames)
103+
}
104+
105+
@Test
106+
fun headers() {
107+
val request = Request(logger, "GET", "1.1", "http://localhost/")
108+
request.addHeader("X-Test", "value")
109+
request.addHeader("Another-Header", "another-value")
110+
111+
assertEquals("X-Test", request.getHeader("X-Test"))
112+
assertEquals("Another-Header", request.getHeader("Another-Header"))
113+
assertEquals(setOf("X-Test", "Another-Header"), request.headerNames)
114+
115+
request.removeHeader("X-Test")
116+
assertEquals("", request.getHeader("X-Test"))
117+
assertEquals(setOf("Another-Header"), request.headerNames)
118+
}
119+
120+
@Test
121+
fun setBodyLength() {
122+
val request = Request(logger, "GET", "1.1", "http://localhost/")
123+
request.bodyLength = 1234
124+
assertEquals(1234, request.bodyLength)
125+
126+
// test negative value is ignored
127+
request.bodyLength = -5
128+
assertEquals(1234, request.bodyLength)
129+
}
130+
}
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 ? headerName : "";
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)