https://kotlinlang.org logo
#http4k
Title
# http4k
a

Arnab

09/30/2021, 11:20 AM
I have the following code:
Copy code
object HelloWorldQueryHandler {
  fun hello(yourname: String) = "Hello $yourname"
}

class GraphQLHandler: GraphQLHandler {
  private val graphql = newGraphQL(
    toSchema(
      SchemaGeneratorConfig(supportedPackages = listOf("no.example.capgemini")),
      listOf(TopLevelObject(HelloWorldQueryHandler))
    )
  ).build()

  override fun invoke(request: GraphQLRequest): GraphQLResponse =
    GraphQLResponse.from(
      graphql.execute {
        Builder()
          .query(request.query)
          .variables(request.variables)
      }
    )
}

fun main() {
  val app = routes("/graphql" bind graphQL(GraphQLHandler()))
  app.asServer(Netty()).start()
}
Now, this works when I use the GraphQL playground, but not when I use the Graphiql client. For the Graphiql client, this just returns an empty response. Am I missing something? Why is there a difference?
d

dave

09/30/2021, 11:45 AM
suggest that you put a debugging filter on the handler
handler.debug()
and sniff what the difference in request is
a

Arnab

09/30/2021, 11:50 AM
@dave: where exactly do you mean? I don’t quite understand where the
handler
object is 😮
d

dave

09/30/2021, 11:51 AM
Copy code
app.debug().asServer(Netty()).start()
a

Arnab

09/30/2021, 11:57 AM
Copy code
***** REQUEST: POST: /graphql *****
POST /graphql HTTP/1.1
Host: localhost:8000
Connection: keep-alive
accept: */*
Origin: null
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_16_0) AppleWebKit/537.36 (KHTML, like Gecko) GraphQLPlayground/1.8.10 Chrome/61.0.3163.100 Electron/2.0.11 Safari/537.36
content-type: application/json
Accept-Encoding: gzip, deflate
Accept-Language: en-GB
content-length: 84

<<stream>>
***** RESPONSE 200 to POST: /graphql *****
HTTP/1.1 200 OK
content-type: application/json; charset=utf-8

{"data":{"hello":"Hello arnab"},"errors":null}
***** REQUEST: POST: /graphql *****
POST /graphql HTTP/1.1
Content-Type: application/json
User-Agent: graphiql-app
Host: localhost:8000
Connection: close
content-length: 65

<<stream>>
***** RESPONSE 400 to POST: /graphql *****
HTTP/1.1 400 Bad Request
What in the world…?
d

dave

10/01/2021, 7:58 AM
put
debug(debugStreams=true)
instead. you'll get the content of the request
a

Arnab

10/04/2021, 9:15 AM
So this:
{"query":"{\n  hello(yourname:\"Arnab\")\n}","variables":null}
gives 400, but this does not
{"operationName":null,"variables":{},"query":"{\n  hello(yourname: \"arnab\")\n}\n"}
I am really not sure what’s going on here. The first one is from Graphiql and the other from GraphQL playground.
In my eyes both are identical except playground sends an empty dict for variables and null for operation name
Apparently sending an empty dict in GraphiQL is the thing 😮 This is really strange
d

dave

10/04/2021, 9:19 AM
I think the problem is that at the moment the vraiables can't be null
Copy code
data class GraphQLRequest(val query: String = "",
                          val operationName: String? = null,
                          val variables: Map<String, Any> = emptyMap()) {
    companion object {
        val requestLens = Body.auto<GraphQLRequest>().toLens()
    }
}
interestingly - the graphql java lib will blow up if it is null:
Copy code
this.variables = assertNotNull(variables, () -> "variables map can't be null");
we can easily fix it, but I'm not sure what the actual spec says about if the fields are nullable
a

Arnab

10/04/2021, 1:49 PM
Well, I took a look at the specs, and as far as I can see here, variables are not required in a query. Nullability. I cannot say anything about however: https://spec.graphql.org/June2018/#sec-Validation What I can say however, is that apollo graphql for instance, has nullable variables: https://github.com/apollographql/apollo-client/blob/cbcf951256b22553bdb065dfa0d32c0a4ca804d3/src/react/hooks/useQuery.ts
d

dave

10/04/2021, 1:50 PM
no problem - we can fix it to not blow up in the absence of variables
a

Arnab

10/04/2021, 1:51 PM
Where is this code from?
Copy code
this.variables = assertNotNull(variables, () -> "variables map can't be null");
(the snippet you posted above)
d

dave

10/04/2021, 1:51 PM
that's from graphql-java library
a

Arnab

10/04/2021, 1:55 PM
This is interesting. I’ll take a look as to how ktor solves this for instance.
d

dave

10/04/2021, 1:55 PM
well it's just a matter of making the field nullable and passing in an empty map instead. it's already fixed
a

Arnab

10/04/2021, 2:02 PM
Oh ok, is the release already out?
d

dave

10/04/2021, 2:13 PM
not yet
it's out now 🙂
3 Views