Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Always use POST for Mutations in AutoPersistedQueries #4011

Merged
merged 1 commit into from
Apr 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -395,16 +395,16 @@ private constructor(
* Configures auto persisted queries.
*
* @param httpMethodForHashedQueries: the [HttpMethod] to use for the initial hashed query that does not send the actual Graphql document.
* [HttpMethod.Get] allows to use caching when available while [HttpMethod.Post] usually allows bigger document sizes.
* [HttpMethod.Get] allows to use caching when available while [HttpMethod.Post] usually allows bigger document sizes. Mutations are
* always sent using [HttpMethod.Post] regardless of this setting.
* Default: [HttpMethod.Get]
*
* @param httpMethodForDocumentQueries: the [HttpMethod] to use for the follow up query that sends the full document if the initial
* hashed query was not found.
* @param httpMethodForDocumentQueries: the [HttpMethod] to use for the follow-up query that sends the full document if the initial
* hashed query was not found. Mutations are always sent using [HttpMethod.Post] regardless of this setting.
* Default: [HttpMethod.Post]
*
* @param enableByDefault: whether to enable Auto Persisted Queries by default. If true, it will set httpMethodForHashedQueries,
* sendApqExtensions=true and sendDocument=false.
* If false it will leave them untouched. You can later use [enableAutoPersistedQueries] to enable them
* @param enableByDefault: whether to enable Auto Persisted Queries by default. You can later use
* [ApolloCall.enableAutoPersistedQueries] on to enable/disable them on individual calls.
*/
@JvmOverloads
fun autoPersistedQueries(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.apollographql.apollo3.AutoPersistedQueryInfo
import com.apollographql.apollo3.api.ApolloRequest
import com.apollographql.apollo3.api.ApolloResponse
import com.apollographql.apollo3.api.Error
import com.apollographql.apollo3.api.Mutation
import com.apollographql.apollo3.api.Operation
import com.apollographql.apollo3.api.http.HttpMethod
import com.apollographql.apollo3.exception.AutoPersistedQueriesNotSupported
Expand All @@ -23,9 +24,12 @@ internal class AutoPersistedQueryInterceptor(
return chain.proceed(request)
}

// Always use POST for mutations to avoid hitting HTTP caches
val isMutation = request.operation is Mutation

@Suppress("NAME_SHADOWING")
val request = request.newBuilder()
.httpMethod(httpMethodForHashedQueries)
.httpMethod(if (isMutation) HttpMethod.Post else httpMethodForHashedQueries)
.sendDocument(false)
.sendApqExtensions(true)
.build()
Expand All @@ -37,7 +41,7 @@ internal class AutoPersistedQueryInterceptor(
isPersistedQueryNotFound(response.errors) -> {
val retryRequest = request
.newBuilder()
.httpMethod(httpMethodForDocumentQueries)
.httpMethod(if (isMutation) HttpMethod.Post else httpMethodForDocumentQueries)
.sendDocument(true)
.sendApqExtensions(true)
.build()
Expand Down Expand Up @@ -71,4 +75,4 @@ internal class AutoPersistedQueryInterceptor(
private const val PROTOCOL_NEGOTIATION_ERROR_QUERY_NOT_FOUND = "PersistedQueryNotFound"
private const val PROTOCOL_NEGOTIATION_ERROR_NOT_SUPPORTED = "PersistedQueryNotSupported"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,18 @@ package test

import com.apollographql.apollo3.ApolloClient
import com.apollographql.apollo3.annotations.ApolloExperimental
import com.apollographql.apollo3.api.Optional
import com.apollographql.apollo3.api.http.HttpMethod
import com.apollographql.apollo3.integration.normalizer.HeroNameQuery
import com.apollographql.apollo3.integration.normalizer.UpdateReviewMutation
import com.apollographql.apollo3.integration.normalizer.type.ColorInput
import com.apollographql.apollo3.integration.normalizer.type.ReviewInput
import com.apollographql.apollo3.mockserver.MockServer
import com.apollographql.apollo3.mockserver.enqueue
import com.apollographql.apollo3.testing.runTest
import testFixtureToUtf8
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertFalse
import kotlin.test.assertTrue

Expand Down Expand Up @@ -80,4 +85,33 @@ class AutoPersistedQueriesTest {
request = mockServer.takeRequest()
assertTrue(request.body.utf8().contains("query"))
}

@Test
fun mutationsAreSentWithPostRegardlessOfSetting() = runTest(before = { setUp() }, after = { tearDown() }) {
mockServer.enqueue("""
{
"errors": [
{
"message": "PersistedQueryNotFound"
}
]
}
""".trimIndent()
)

mockServer.enqueue(testFixtureToUtf8("UpdateReviewResponse.json"))

val apolloClient = ApolloClient.Builder()
.serverUrl(mockServer.url())
.autoPersistedQueries(httpMethodForHashedQueries = HttpMethod.Get, httpMethodForDocumentQueries = HttpMethod.Get)
.build()

apolloClient.mutation(UpdateReviewMutation("100", ReviewInput(5, Optional.Absent, ColorInput(Optional.Absent, Optional.Absent, Optional.Absent)))).execute()

var request = mockServer.takeRequest()
assertEquals("POST", request.method)
request = mockServer.takeRequest()
assertEquals("POST", request.method)
}

}