Skip to content

Commit

Permalink
fix: create MessageDigest when needed (#1906)
Browse files Browse the repository at this point in the history
### 📝 Description
`MessageDiggest` is NOT thread safe, if multiple queries are being
executed concurrently it might cause a race condition and send back a
`PersistedQueryIdInvalid` error

https://opensource.expediagroup.com/graphql-kotlin/docs/server/automatic-persisted-queries/#errors

instead we will create a `MessageDigest` instance each time.
  • Loading branch information
samuelAndalon authored Jan 3, 2024
1 parent 486bcbd commit 34687a7
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,18 @@ import java.math.BigInteger
import java.nio.charset.StandardCharsets
import java.security.MessageDigest

internal val MESSAGE_DIGEST: MessageDigest = MessageDigest.getInstance("SHA-256")

fun GraphQLClientRequest<*>.getQueryId(): String =
String.format(
fun GraphQLClientRequest<*>.getQueryId(): String {
val messageDigest = MessageDigest.getInstance("SHA-256")
return String.format(
"%064x",
BigInteger(1, MESSAGE_DIGEST.digest(this.query?.toByteArray(StandardCharsets.UTF_8)))
).also {
MESSAGE_DIGEST.reset()
}
BigInteger(1, messageDigest.digest(this.query?.toByteArray(StandardCharsets.UTF_8)))
)
}

fun AutomaticPersistedQueriesExtension.toQueryParamString(): String =
"""{"persistedQuery":{"version":$version,"sha256Hash":"$sha256Hash"}}"""

fun AutomaticPersistedQueriesExtension.toQueryParamString() = """{"persistedQuery":{"version":$version,"sha256Hash":"$sha256Hash"}}"""
fun AutomaticPersistedQueriesExtension.toExtentionsBodyMap() = mapOf(
fun AutomaticPersistedQueriesExtension.toExtensionsBodyMap(): Map<String, Map<String, Any>> = mapOf(
"persistedQuery" to mapOf(
"version" to version,
"sha256Hash" to sha256Hash
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ package com.expediagroup.graphql.client.ktor

import com.expediagroup.graphql.client.GraphQLClient
import com.expediagroup.graphql.client.extensions.getQueryId
import com.expediagroup.graphql.client.extensions.toExtentionsBodyMap
import com.expediagroup.graphql.client.extensions.toExtensionsBodyMap
import com.expediagroup.graphql.client.extensions.toQueryParamString
import com.expediagroup.graphql.client.serializer.GraphQLClientSerializer
import com.expediagroup.graphql.client.serializer.defaultGraphQLSerializer
Expand Down Expand Up @@ -60,8 +60,8 @@ open class GraphQLKtorClient(
sha256Hash = queryId
)
val extensions = request.extensions?.let {
automaticPersistedQueriesExtension.toExtentionsBodyMap().plus(it)
} ?: automaticPersistedQueriesExtension.toExtentionsBodyMap()
automaticPersistedQueriesExtension.toExtensionsBodyMap().plus(it)
} ?: automaticPersistedQueriesExtension.toExtensionsBodyMap()

val apqRawResultWithoutQuery: String = when (automaticPersistedQueriesSettings.httpMethod) {
is AutomaticPersistedQueriesSettings.HttpMethod.GET -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ package com.expediagroup.graphql.client.spring

import com.expediagroup.graphql.client.GraphQLClient
import com.expediagroup.graphql.client.extensions.getQueryId
import com.expediagroup.graphql.client.extensions.toExtentionsBodyMap
import com.expediagroup.graphql.client.extensions.toExtensionsBodyMap
import com.expediagroup.graphql.client.extensions.toQueryParamString
import com.expediagroup.graphql.client.serializer.GraphQLClientSerializer
import com.expediagroup.graphql.client.serializer.defaultGraphQLSerializer
Expand Down Expand Up @@ -63,8 +63,8 @@ open class GraphQLWebClient(
sha256Hash = queryId
)
val extensions = request.extensions?.let {
automaticPersistedQueriesExtension.toExtentionsBodyMap().plus(it)
} ?: automaticPersistedQueriesExtension.toExtentionsBodyMap()
automaticPersistedQueriesExtension.toExtensionsBodyMap().plus(it)
} ?: automaticPersistedQueriesExtension.toExtensionsBodyMap()

val apqRawResultWithoutQuery: String = when (automaticPersistedQueriesSettings.httpMethod) {
is AutomaticPersistedQueriesSettings.HttpMethod.GET -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import java.nio.charset.StandardCharsets
import java.security.MessageDigest

internal const val APQ_EXTENSION_KEY: String = "persistedQuery"
internal val MESSAGE_DIGEST: MessageDigest = MessageDigest.getInstance("SHA-256")

@Suppress("UNCHECKED_CAST")
fun ExecutionInput.getAutomaticPersistedQueriesExtension(): AutomaticPersistedQueriesExtension? =
Expand All @@ -34,13 +33,13 @@ fun ExecutionInput.getAutomaticPersistedQueriesExtension(): AutomaticPersistedQu
null
}

fun ExecutionInput.getQueryId(): String =
String.format(
fun ExecutionInput.getQueryId(): String {
val messageDigest = MessageDigest.getInstance("SHA-256")
return String.format(
"%064x",
BigInteger(1, MESSAGE_DIGEST.digest(this.query.toByteArray(StandardCharsets.UTF_8)))
).also {
MESSAGE_DIGEST.reset()
}
BigInteger(1, messageDigest.digest(this.query.toByteArray(StandardCharsets.UTF_8)))
)
}

fun ExecutionInput.isAutomaticPersistedQueriesExtensionInvalid(
extension: AutomaticPersistedQueriesExtension
Expand Down

0 comments on commit 34687a7

Please sign in to comment.