Skip to content

Commit e4c5daf

Browse files
committed
Allow # in app/ user-agent metadata
1 parent 0d77f0f commit e4c5daf

File tree

2 files changed

+20
-12
lines changed

2 files changed

+20
-12
lines changed

aws-runtime/aws-http/common/src/aws/sdk/kotlin/runtime/http/AwsUserAgentMetadata.kt

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ public data class AwsUserAgentMetadata(
7373
add(languageMetadata)
7474
execEnvMetadata?.let(::add)
7575
customMetadata?.typedExtras?.filterIsInstance<ConfigMetadata>()?.forEach(::add)
76-
appId?.let { add(uaPair("app", it)) }
76+
appId?.let { add(uaPair("app", value = it)) }
7777
customMetadata?.typedExtras?.filterIsInstance<FeatureMetadata>()?.forEach(::add)
7878
frameworkMetadata?.let(::add)
7979

@@ -190,7 +190,7 @@ internal expect fun platformLanguageMetadata(): LanguageMetadata
190190
*/
191191
@InternalSdkApi
192192
public data class ExecutionEnvMetadata(val name: String) {
193-
override fun toString(): String = uaPair("exec-env", name)
193+
override fun toString(): String = uaPair("exec-env", value = name)
194194
}
195195

196196
/**
@@ -223,21 +223,29 @@ private fun detectExecEnv(platform: PlatformEnvironProvider): ExecutionEnvMetada
223223
// tchar_no_hash = "!" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." /
224224
// "^" / "_" / "`" / "|" / "~" / DIGIT / ALPHA
225225
private val VALID_TCHAR_NO_HASH = setOf('!', '$', '%', '&', '\'', '*', '+', '-', '.', '^', '_', '`', '|', '~')
226+
private val VALID_TCHAR = VALID_TCHAR_NO_HASH + '#'
226227

227-
internal fun uaPair(category: String, key: String, value: String? = null): String =
228-
if (value == null) {
229-
"${category.encodeUaToken()}/${key.encodeUaToken()}"
230-
} else {
231-
"${category.encodeUaToken()}/${key.encodeUaToken()}#${value.encodeUaToken()}"
232-
}
233228

234-
private fun String.encodeUaToken(): String {
229+
internal fun uaPair(category: String, key: String? = null, value: String? = null): String = when {
230+
key == null && value == null -> category.encodeUaName()
231+
value == null -> "${category.encodeUaName()}/${key!!.encodeUaName()}"
232+
key == null -> "${category.encodeUaName()}/${value.encodeUaValue()}"
233+
else -> "${category.encodeUaName()}/${key.encodeUaName()}#${value.encodeUaValue()}"
234+
}
235+
236+
private fun String.encodeUaName() = encodeUaString(VALID_TCHAR_NO_HASH)
237+
private fun String.encodeUaValue() = encodeUaString(VALID_TCHAR)
238+
239+
/**
240+
* Encode a UA string, allowing only A-Z, a-z, 0-9, and characters in `charSet`.
241+
*/
242+
private fun String.encodeUaString(charSet: Set<Char>): String {
235243
val str = this
236244
return buildString(str.length) {
237245
for (chr in str) {
238246
when (chr) {
239247
' ' -> append("_")
240-
in 'a'..'z', in 'A'..'Z', in '0'..'9', in VALID_TCHAR_NO_HASH -> append(chr)
248+
in 'a'..'z', in 'A'..'Z', in '0'..'9', in charSet -> append(chr)
241249
else -> continue
242250
}
243251
}

aws-runtime/aws-http/common/test/aws/sdk/kotlin/runtime/http/AwsUserAgentMetadataTest.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ class AwsUserAgentMetadataTest {
3131
val langMeta = LanguageMetadata("1.4.31", mapOf("jvmVersion" to "1.11"))
3232
val execEnvMeta = ExecutionEnvMetadata("lambda")
3333
val frameworkMeta = FrameworkMetadata("amplify", "1.2.3")
34-
val appId = "Foo Service"
34+
val appId = "Foo Service #1.2.3"
3535
val custom = CustomUserAgentMetadata(
3636
extras = mapOf("foo" to "bar", "internal" to "true"),
3737
typedExtras = listOf(
@@ -53,7 +53,7 @@ class AwsUserAgentMetadataTest {
5353
"exec-env/lambda",
5454
"cfg/retry-mode#standard",
5555
"cfg/http-engine#okhttp",
56-
"app/Foo_Service",
56+
"app/Foo_Service_#1.2.3",
5757
"ft/paginator",
5858
"ft/ddb-hll#4.5.6",
5959
"lib/amplify#1.2.3",

0 commit comments

Comments
 (0)