I wanted to test my Caliban Http4s Webservice.
In Http4sAdapter
it uses GraphQLRequest
to model a Request Body.
case class GraphQLRequest(
query: String,
operationName: Option[String],
variables: Option[Map[String, InputValue]])
...
query <- req.attemptAs[GraphQLRequest].value.absolve
...
So I thought on the client side I could use it as well.
A simple Request works:
GraphQLRequest("""query{
| characters(origin: EARTH) {
| name
| nicknames
| origin
| }
|}""".stripMargin, None, None)
But if I use variables it doesn't:
GraphQLRequest("""query($origin: String){
| characters(origin: $origin) {
| name
| nicknames
| origin
| }
|}""".stripMargin, None, Some(Map("origin" -> StringValue("EARTH"))))
It just hangs - there is not even an exception.
I tried with 0.4.2
and 0.5.0
.
I added a Gist to show the client code. It uses Circe and Sttp: Client Gist
The main problem can be seen in your gist: the variables encoded into JSON are not what is expected by the server.
You currently have:
"origin": {
"StringValue": {
"value": "EARTH"
}
}
and you should only have:
"origin": "EARTH"
That value is an InputValue
in Caliban, and Caliban provides an Encoder
for Circe. However you seem to be using Circe generic auto-derivation which is not picking up Caliban's Encoder
but instead tries to derive InputValue
on its own, giving an incorrect result.
I recommend using semi-auto derivation in circe-generic or even using circe-derivation which will pick up Caliban's Encoder
properly.
Example with circe-generic:
val req = GraphQLRequest(
"""query($origin: String){
| characters(origin: $origin) {
| name
| nicknames
| origin
| }
|}""".stripMargin,
None,
Some(Map("origin" -> StringValue("EARTH")))
)
import io.circe.syntax._
import io.circe.generic.semiauto._
implicit val enc = deriveEncoder[GraphQLRequest]
println(req.asJson)
gives the expected JSON:
{
"query" : "query($origin: String){\n characters(origin: $origin) {\n name\n nicknames\n origin\n }\n}",
"operationName" : null,
"variables" : {
"origin" : "EARTH"
}
}