Skip to content

Commit 81af5b3

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

File tree

8 files changed

+636
-47
lines changed

8 files changed

+636
-47
lines changed

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

Lines changed: 35 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,25 @@ 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 getHttpVersion ()Ljava/lang/String;
663+
public fun getQueryParameter (Ljava/lang/String;)Ljava/lang/String;
664+
public fun getQueryParameterNames ()Ljava/util/Set;
665+
public fun getUrl ()Ljava/lang/String;
666+
public fun removeQueryParameter (Ljava/lang/String;)V
667+
public fun setHttpMethod (Ljava/lang/String;)V
668+
public fun setHttpVersion (Ljava/lang/String;)V
669+
public fun setUrl (Ljava/lang/String;)V
670+
public fun toStream (Lcom/bugsnag/android/JsonStream;)V
671+
}
672+
673+
public final class com/bugsnag/android/Response : com/bugsnag/android/AbstractHttpEntity, com/bugsnag/android/JsonStream$Streamable {
674+
public fun getStatusCode ()I
675+
public fun setStatusCode (I)V
676+
public fun toStream (Lcom/bugsnag/android/JsonStream;)V
677+
}
678+
644679
public final class com/bugsnag/android/Session : com/bugsnag/android/Deliverable, com/bugsnag/android/JsonStream$Streamable, com/bugsnag/android/UserAware {
645680
public fun getApiKey ()Ljava/lang/String;
646681
public fun getApp ()Lcom/bugsnag/android/App;
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
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+
assertEquals(0L, request.bodyLength)
52+
}
53+
54+
@Test
55+
fun setHttpMethod() {
56+
val request = Request(logger, "GET", "1.1", "http://localhost/")
57+
assertEquals("GET", request.httpMethod)
58+
59+
request.httpMethod = "POST"
60+
assertEquals("POST", request.httpMethod)
61+
}
62+
63+
@Test
64+
fun setHttpVersion() {
65+
val request = Request(logger, "1.1", "1.1", "http://localhost/")
66+
assertEquals("1.1", request.httpVersion)
67+
68+
request.httpVersion = "1.0"
69+
assertEquals("1.0", request.httpVersion)
70+
}
71+
72+
@Test
73+
fun setUrl() {
74+
val request = Request(logger, "GET", "1.1", "http://localhost/")
75+
assertEquals("http://localhost/", request.url)
76+
77+
request.url = "https://google.com"
78+
assertEquals("https://google.com", request.url)
79+
}
80+
81+
@Test
82+
fun setUrlWithQuery() {
83+
val request = Request(logger, "GET", "1.1", "http://localhost/")
84+
request.url = "http://foo.com?a=1&b=2"
85+
assertEquals("http://foo.com", request.url)
86+
assertEquals("1", request.getQueryParameter("a"))
87+
assertEquals("2", request.getQueryParameter("b"))
88+
assertEquals(setOf("a", "b"), request.queryParameterNames)
89+
}
90+
91+
@Test
92+
fun queryParameters() {
93+
val request = Request(logger, "GET", "1.1", "http://localhost/")
94+
request.addQueryParameter("foo", "bar")
95+
request.addQueryParameter("another", "param")
96+
97+
assertEquals("bar", request.getQueryParameter("foo"))
98+
assertEquals("param", request.getQueryParameter("another"))
99+
assertEquals(setOf("foo", "another"), request.queryParameterNames)
100+
101+
request.removeQueryParameter("foo")
102+
assertNull(request.getQueryParameter("foo"))
103+
assertEquals(setOf("another"), request.queryParameterNames)
104+
}
105+
106+
@Test
107+
fun headers() {
108+
val request = Request(logger, "GET", "1.1", "http://localhost/")
109+
request.addHeader("X-Test", "value")
110+
request.addHeader("Another-Header", "another-value")
111+
112+
assertEquals("X-Test", request.getHeader("X-Test"))
113+
assertEquals("Another-Header", request.getHeader("Another-Header"))
114+
assertEquals(setOf("X-Test", "Another-Header"), request.headerNames)
115+
116+
request.removeHeader("X-Test")
117+
assertEquals("", request.getHeader("X-Test"))
118+
assertEquals(setOf("Another-Header"), request.headerNames)
119+
}
120+
121+
@Test
122+
fun setBodyLength() {
123+
val request = Request(logger, "GET", "1.1", "http://localhost/")
124+
request.bodyLength = 1234
125+
assertEquals(1234, request.bodyLength)
126+
127+
// test negative value is ignored
128+
request.bodyLength = -5
129+
assertEquals(1234, request.bodyLength)
130+
}
131+
}
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)