Open namdroid opened 1 month ago
Hi 👋 Apollo Kotlin uses codegen to generate models for your operation. In this example, you should get a GetBestSellers(category: ProductCategory)
class where you can pass your variables. You can take a look at https://www.apollographql.com/docs/kotlin/advanced/operation-variables for more details.
Hi Martin, of course i can pass parameter to GetBestSellers directly, but waht i need is a addtional variables
{"query":"query
{
footer(lang: GERMAN) {
links {
text
url
}
}
}
}", "variables":{"appName":"myapp"}}'
in javascript should be:
const gqlResp = await client
.query({
query,
variables: {
lang,
appName: 'myApp',
...moreVariables,
},
fetchPolicy: 'no-cache',
});
Looking at your initial query:
query GetBestSellers($category: ProductCategory){
bestSellers(category: $category) {
title
}
}
This query defines a $category
variable, which is sent as JSON and Apollo Kotlin will serialize it automatically when you construct a GetBestSellers
operation:
val operation = GetBestSellers(ProductCategory(Books))
Your second query doesn't have an appName
variable:
query {
footer(lang: GERMAN) {
links {
text
url
}
}
}
You could patch the HTTP POST body to include additional variables if that's what you're trying to do but I would recommend against that. variables
is for GraphQL variables. It's surprising to pass values there that are not in your GraphQL operation.
If you're trying to send additional context to your server, I would recommend using an HTTP header instead.
Ho can i patch the HTTP POST body to include additional variables ?
The most efficient way is to implement your own HttpRequestComposer
.
Another easier albeit slightly less efficient (because it needs to rewrite the post body), is to use OkHttp interceptors
thanks martin, so here is my HttpRequestComposer class:
class GraphQLHttpRequestComposer(url: String, gson: Gson) : HttpRequestComposer {
override fun <D : Operation.Data> compose(apolloRequest: ApolloRequest<D>): HttpRequest {
val operation = apolloRequest.operation
// Create a MapJsonWriter to capture variables
val mapJsonWriter = MapJsonWriter()
// Convert the captured map to a JsonObject
val variablesJson = gson.toJsonTree(mapJsonWriter.root()).asJsonObject
// Add appName to variables
variablesJson.addProperty("appName", „MyApp“)
// Create the full request body
val bodyJson = JsonObject().apply {
addProperty("query", operation.document())
addProperty("operationName", operation.name())
add("variables", variablesJson)
}
val bodyString = gson.toJson(bodyJson)
val httpBody = object : HttpBody {
override val contentLength: Long = bodyString.toByteArray().size.toLong()
override val contentType: String = "application/json; charset=utf-8"
override fun writeTo(bufferedSink: BufferedSink) {
bufferedSink.writeUtf8(bodyString)
}
}
return HttpRequest.Builder(HttpMethod.Post, "url")
.addHeader("Content-Type", "application/json")
.body(httpBody)
.build()
}
}
fun provideApolloClient(okHttpClient: OkHttpClient, graphqlUrl: String): ApolloClient {
val networkTransport = HttpNetworkTransport.Builder()
.httpRequestComposer(GraphQLHttpRequestComposer(graphqlUrl, gson))
.okHttpClient(okHttpClient)
.build()
return ApolloClient.Builder()
.networkTransport(networkTransport)
.addInterceptor(LoggingApolloInterceptor())
.httpMethod(HttpMethod.Get)
.autoPersistedQueries()
.build()
}
But it don't work !I don't know why
may new method added to Apollo client in the future that support variables in request body ?
Try something like below (wildly untested):
class MyHttpRequestComposer(val serverUrl: String): HttpRequestComposer {
override fun <D : Operation.Data> compose(apolloRequest: ApolloRequest<D>): HttpRequest {
check(apolloRequest.httpMethod == HttpMethod.Post) {
"This composer only supports POST"
}
val operation = apolloRequest.operation
val customScalarAdapters = apolloRequest.executionContext[CustomScalarAdapters]!!
val body = buildJsonByteString {
writeObject {
name("query")
value(operation.document())
name("operationName")
value(operation.name())
name("variables")
writeObject {
operation.serializeVariables(this, customScalarAdapters, false)
// Add your variables here
name("appName")
value("MyAppName")
}
}
}
return HttpRequest.Builder(HttpMethod.Post, serverUrl)
.body(
object : HttpBody {
override val contentType = "application/json"
override val contentLength = body.size.toLong()
override fun writeTo(bufferedSink: BufferedSink) {
bufferedSink.write(body)
}
}
)
.build()
}
}
may new method added to Apollo client in the future that support variables in request body ?
That is very unlikely. As said before, sending extra fields in GraphQL variables is not standard. Is there a reason you cannot use a HTTP header or another way for this?
Question
my request shows like that:
How can i pass "variables":{"category":"BOOKS"}} ?