Skip to content

Commit 8bca517

Browse files
committed
feat: make webhook headers case insensitive (#100)
1 parent 58c3b1b commit 8bca517

3 files changed

Lines changed: 24 additions & 20 deletions

File tree

lithic-java-core/src/main/kotlin/com/lithic/api/core/Utils.kt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,17 @@ internal fun <K, V> ListMultimap<K, V>.toUnmodifiable(): ListMultimap<K, V> {
4343

4444
return Multimaps.unmodifiableListMultimap(this)
4545
}
46+
47+
@JvmSynthetic
48+
internal fun ListMultimap<String, String>.getRequiredHeader(header: String): String {
49+
val value =
50+
entries()
51+
.stream()
52+
.filter { entry -> entry.key.equals(header, ignoreCase = true) }
53+
.map { entry -> entry.value }
54+
.findFirst()
55+
if (!value.isPresent) {
56+
throw LithicInvalidDataException("Could not find $header header")
57+
}
58+
return value.get()
59+
}

lithic-java-core/src/main/kotlin/com/lithic/api/services/async/WebhookServiceAsyncImpl.kt

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import com.fasterxml.jackson.core.JsonProcessingException
66
import com.google.common.collect.ListMultimap
77
import com.lithic.api.core.ClientOptions
88
import com.lithic.api.core.JsonValue
9+
import com.lithic.api.core.getRequiredHeader
910
import com.lithic.api.core.http.HttpResponse.Handler
1011
import com.lithic.api.errors.LithicError
1112
import com.lithic.api.errors.LithicException
@@ -56,15 +57,9 @@ constructor(
5657
throw LithicException("Invalid webhook secret")
5758
}
5859

59-
val msgId =
60-
headers.get("webhook-id").getOrNull(0)
61-
?: throw LithicException("Could not find webhook-id header")
62-
val msgSignture =
63-
headers.get("webhook-signature").getOrNull(0)
64-
?: throw LithicException("Could not find webhook-signature header")
65-
val msgTimestamp =
66-
headers.get("webhook-timestamp").getOrNull(0)
67-
?: throw LithicException("Could not find webhook-timestamp header")
60+
val msgId = headers.getRequiredHeader("webhook-id")
61+
val msgSignature = headers.getRequiredHeader("webhook-signature")
62+
val msgTimestamp = headers.getRequiredHeader("webhook-timestamp")
6863

6964
val timestamp =
7065
try {
@@ -86,7 +81,7 @@ constructor(
8681
val expectedSignature =
8782
mac.doFinal("$msgId.${timestamp.epochSecond}.$payload".toByteArray())
8883

89-
msgSignture.splitToSequence(" ").forEach {
84+
msgSignature.splitToSequence(" ").forEach {
9085
val parts = it.split(",")
9186
if (parts.size != 2) {
9287
return@forEach

lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/WebhookServiceImpl.kt

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import com.fasterxml.jackson.core.JsonProcessingException
66
import com.google.common.collect.ListMultimap
77
import com.lithic.api.core.ClientOptions
88
import com.lithic.api.core.JsonValue
9+
import com.lithic.api.core.getRequiredHeader
910
import com.lithic.api.core.http.HttpResponse.Handler
1011
import com.lithic.api.errors.LithicError
1112
import com.lithic.api.errors.LithicException
@@ -56,15 +57,9 @@ constructor(
5657
throw LithicException("Invalid webhook secret")
5758
}
5859

59-
val msgId =
60-
headers.get("webhook-id").getOrNull(0)
61-
?: throw LithicException("Could not find webhook-id header")
62-
val msgSignture =
63-
headers.get("webhook-signature").getOrNull(0)
64-
?: throw LithicException("Could not find webhook-signature header")
65-
val msgTimestamp =
66-
headers.get("webhook-timestamp").getOrNull(0)
67-
?: throw LithicException("Could not find webhook-timestamp header")
60+
val msgId = headers.getRequiredHeader("webhook-id")
61+
val msgSignature = headers.getRequiredHeader("webhook-signature")
62+
val msgTimestamp = headers.getRequiredHeader("webhook-timestamp")
6863

6964
val timestamp =
7065
try {
@@ -86,7 +81,7 @@ constructor(
8681
val expectedSignature =
8782
mac.doFinal("$msgId.${timestamp.epochSecond}.$payload".toByteArray())
8883

89-
msgSignture.splitToSequence(" ").forEach {
84+
msgSignature.splitToSequence(" ").forEach {
9085
val parts = it.split(",")
9186
if (parts.size != 2) {
9287
return@forEach

0 commit comments

Comments
 (0)