Skip to content

Commit bdb9c74

Browse files
authored
Consolidate code solely needed by HUC instrumentation (#2601)
## Goal Clean up HUC to make extraction into a separate module easier. This involved converting `HttpUrlConnectionTracker`​ into Kotlin and consolidated related logic into to, much of which were exposed via difficult-to-test Java static objects and methods, because that's what you have to do to work with the HUC API if you want to do what we are doing. Other static helpers were converted into Kotlin and moved out of the `embrace-android-sdk` module as well, while leaving much of the HUC instrumentation unchanged (and in Java).
1 parent 98f5b44 commit bdb9c74

File tree

23 files changed

+416
-457
lines changed

23 files changed

+416
-457
lines changed

embrace-android-api/api/embrace-android-api.api

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -135,19 +135,6 @@ public abstract interface class io/embrace/android/embracesdk/internal/api/UserA
135135
public abstract fun setUsername (Ljava/lang/String;)V
136136
}
137137

138-
public class io/embrace/android/embracesdk/internal/network/http/EmbraceHttpPathOverride {
139-
protected static final field PATH_OVERRIDE Ljava/lang/String;
140-
public fun <init> ()V
141-
public static fun getURLString (Lio/embrace/android/embracesdk/internal/network/http/HttpPathOverrideRequest;)Ljava/lang/String;
142-
public static fun getURLString (Lio/embrace/android/embracesdk/internal/network/http/HttpPathOverrideRequest;Ljava/lang/String;)Ljava/lang/String;
143-
}
144-
145-
public abstract interface class io/embrace/android/embracesdk/internal/network/http/HttpPathOverrideRequest {
146-
public abstract fun getHeaderByName (Ljava/lang/String;)Ljava/lang/String;
147-
public abstract fun getOverriddenURL (Ljava/lang/String;)Ljava/lang/String;
148-
public abstract fun getURLString ()Ljava/lang/String;
149-
}
150-
151138
public final class io/embrace/android/embracesdk/internal/network/http/NetworkCaptureData {
152139
public fun <init> (Ljava/util/Map;Ljava/lang/String;[BLjava/util/Map;[BLjava/lang/String;)V
153140
public synthetic fun <init> (Ljava/util/Map;Ljava/lang/String;[BLjava/util/Map;[BLjava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V

embrace-android-api/src/main/java/io/embrace/android/embracesdk/internal/network/http/EmbraceHttpPathOverride.java

Lines changed: 0 additions & 75 deletions
This file was deleted.

embrace-android-api/src/main/java/io/embrace/android/embracesdk/internal/network/http/HttpPathOverrideRequest.java

Lines changed: 0 additions & 21 deletions
This file was deleted.
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package io.embrace.android.embracesdk.internal.network.logging
2+
3+
import io.embrace.android.embracesdk.annotation.InternalApi
4+
import java.nio.charset.StandardCharsets
5+
import java.util.regex.Pattern
6+
7+
/**
8+
* Header used to override the URL's relative path
9+
*/
10+
const val PATH_OVERRIDE: String = "x-emb-path"
11+
12+
/**
13+
* Max length of relative path override
14+
*/
15+
private const val RELATIVE_PATH_MAX_LENGTH = 1024
16+
17+
/**
18+
* Allowed characters in relative path
19+
* As per https://tools.ietf.org/html/rfc3986#section-2 and https://stackoverflow.com/a/1547940.
20+
* Removed certain characters we do not want present: ?#
21+
*/
22+
private val RELATIVE_PATH_PATTERN: Pattern = Pattern.compile("[A-Za-z0-9-._~:/\\[\\]@!$&'()*+,;=]+")
23+
24+
@JvmOverloads
25+
@InternalApi
26+
fun getOverriddenURLString(
27+
request: HttpPathOverrideRequest,
28+
pathOverride: String? = request.getHeaderByName(PATH_OVERRIDE)
29+
): String {
30+
val url = try {
31+
if (pathOverride != null && validatePathOverride(pathOverride)) {
32+
request.getOverriddenURL(pathOverride)
33+
} else {
34+
request.getURLString()
35+
}
36+
} catch (_: Exception) {
37+
request.getURLString()
38+
}
39+
return url
40+
}
41+
42+
private fun validatePathOverride(path: String?): Boolean {
43+
if (path == null) {
44+
return false
45+
}
46+
if (path.isEmpty()) {
47+
return false
48+
}
49+
if (path.length > RELATIVE_PATH_MAX_LENGTH) {
50+
return false
51+
}
52+
if (!StandardCharsets.US_ASCII.newEncoder().canEncode(path)) {
53+
return false
54+
}
55+
if (!path.startsWith("/")) {
56+
return false
57+
}
58+
if (!RELATIVE_PATH_PATTERN.matcher(path).matches()) {
59+
return false
60+
}
61+
62+
return true
63+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package io.embrace.android.embracesdk.internal.network.logging
2+
3+
import io.embrace.android.embracesdk.annotation.InternalApi
4+
5+
@InternalApi
6+
interface HttpPathOverrideRequest {
7+
fun getHeaderByName(name: String): String?
8+
9+
fun getOverriddenURL(pathOverride: String): String
10+
11+
fun getURLString(): String
12+
}

embrace-android-core/src/main/kotlin/io/embrace/android/embracesdk/internal/utils/exceptions/Unchecked.kt

Lines changed: 0 additions & 41 deletions
This file was deleted.
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package io.embrace.android.embracesdk.internal.network.logging
2+
3+
import org.junit.Assert.assertEquals
4+
import org.junit.Test
5+
6+
internal class EmbraceHttpPathOverrideTest {
7+
8+
@Test
9+
fun `check override path validity`() {
10+
val request: HttpPathOverrideRequest = FakeHttpOverrideRequest(
11+
urlString = DEFAULT_URL,
12+
overriddenUrlStringProvider = ::customUrlProvider
13+
)
14+
15+
assertEquals(DEFAULT_URL, getOverriddenURLString(request, null))
16+
assertEquals(DEFAULT_URL, getOverriddenURLString(request, ""))
17+
assertEquals(DEFAULT_URL, getOverriddenURLString(request, "/a".repeat(1025)))
18+
assertEquals(DEFAULT_URL, getOverriddenURLString(request, "/屈福特"))
19+
assertEquals(DEFAULT_URL, getOverriddenURLString(request, "watford"))
20+
assertEquals(DEFAULT_URL, getOverriddenURLString(request, "/custom#"))
21+
assertEquals(DEFAULT_URL, getOverriddenURLString(request, ""))
22+
assertEquals(DEFAULT_URL, getOverriddenURLString(request, "/error"))
23+
assertEquals(CUSTOM_URL, getOverriddenURLString(request, CUSTOM_PATH))
24+
}
25+
26+
companion object {
27+
private fun customUrlProvider(pathOverride: String): String {
28+
return when (pathOverride) {
29+
CUSTOM_PATH -> {
30+
CUSTOM_URL
31+
}
32+
33+
"/error" -> {
34+
throw RuntimeException()
35+
}
36+
37+
else -> {
38+
DEFAULT_URL
39+
}
40+
}
41+
}
42+
private const val DEFAULT_URL = "https://embrace.io/default-path"
43+
private const val CUSTOM_PATH = "/custom-path"
44+
private const val CUSTOM_URL = "https://embrace.io$CUSTOM_PATH"
45+
}
46+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package io.embrace.android.embracesdk.internal.network.logging
2+
3+
internal class FakeHttpOverrideRequest(
4+
private val headerByName: String? = null,
5+
private val urlString: String = "https://fakeurl.fake",
6+
private val overriddenUrlStringProvider: (pathOverride: String) -> String = { urlString },
7+
) : HttpPathOverrideRequest {
8+
override fun getHeaderByName(name: String): String? = headerByName
9+
10+
override fun getOverriddenURL(pathOverride: String): String = overriddenUrlStringProvider.invoke(pathOverride)
11+
12+
override fun getURLString(): String = urlString
13+
}

embrace-android-infra/src/main/kotlin/io/embrace/android/embracesdk/internal/logging/InternalErrorType.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,5 @@ enum class InternalErrorType {
3737
NATIVE_READ_FAIL,
3838
APP_LAUNCH_TRACE_FAIL,
3939
UI_CALLBACK_FAIL,
40+
INSTRUMENTATION_REG_FAIL,
4041
}

embrace-android-okhttp3/src/main/java/io/embrace/android/embracesdk/okhttp3/EmbraceOkHttp3ApplicationInterceptor.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package io.embrace.android.embracesdk.okhttp3
33
import io.embrace.android.embracesdk.Embrace
44
import io.embrace.android.embracesdk.internal.EmbraceInternalApi
55
import io.embrace.android.embracesdk.internal.EmbraceInternalApi.CUSTOM_TRACE_ID_HEADER_NAME
6-
import io.embrace.android.embracesdk.internal.network.http.EmbraceHttpPathOverride
6+
import io.embrace.android.embracesdk.internal.network.logging.getOverriddenURLString
77
import io.embrace.android.embracesdk.network.EmbraceNetworkRequest
88
import io.embrace.android.embracesdk.network.http.HttpMethod
99
import okhttp3.Interceptor
@@ -37,7 +37,7 @@ class EmbraceOkHttp3ApplicationInterceptor(
3737
} catch (e: EmbraceCustomPathException) {
3838
if (embrace.isStarted) {
3939
val urlString =
40-
EmbraceHttpPathOverride.getURLString(EmbraceOkHttp3PathOverrideRequest(request), e.customPath)
40+
getOverriddenURLString(EmbraceOkHttp3PathOverrideRequest(request), e.customPath)
4141
embrace.recordNetworkRequest(
4242
EmbraceNetworkRequest.fromIncompleteRequest(
4343
urlString,
@@ -62,7 +62,7 @@ class EmbraceOkHttp3ApplicationInterceptor(
6262
} catch (e: Exception) {
6363
// we are interested in errors.
6464
if (embrace.isStarted) {
65-
val urlString = EmbraceHttpPathOverride.getURLString(EmbraceOkHttp3PathOverrideRequest(request))
65+
val urlString = getOverriddenURLString(EmbraceOkHttp3PathOverrideRequest(request))
6666
val errorType = e.javaClass.canonicalName
6767
val errorMessage = e.message
6868
embrace.recordNetworkRequest(

0 commit comments

Comments
 (0)