Можно ли использовать GraphQLRequest для клиента в Caliban? - PullRequest
0 голосов
/ 29 января 2020

Я хотел протестировать свой веб-сервис Caliban Http4s.

В Http4sAdapter он использует GraphQLRequest для моделирования тела запроса.

case class GraphQLRequest(
   query: String,
   operationName: Option[String],
   variables: Option[Map[String, InputValue]])
...
query    <- req.attemptAs[GraphQLRequest].value.absolve
...

Так что я подумал на стороне клиента: может использовать его также.

Простой запрос работает:

 GraphQLRequest("""query{
                         |  characters(origin: EARTH) {
                         |    name
                         |    nicknames
                         |    origin
                         |  }
                         |}""".stripMargin, None, None)

Но если я использую переменные, он не:

GraphQLRequest("""query($origin: String){
                 |  characters(origin: $origin) {
                 |    name
                 |    nicknames
                 |    origin
                 |  }
                 |}""".stripMargin, None, Some(Map("origin" -> StringValue("EARTH"))))

Он просто висит - там даже не исключение.

Я пытался с 0.4.2 и 0.5.0.

Я добавил Gist, чтобы показать код клиента. Он использует Circe и Sttp : Client Gist

1 Ответ

1 голос
/ 30 января 2020

Основная проблема видна в вашей сущности: переменные, закодированные в JSON, не соответствуют ожидаемым сервером.

В настоящее время у вас есть:

"origin": {
  "StringValue": {
    "value": "EARTH"
  }
}

и вы должно иметь только:

"origin": "EARTH"

Это значение равно InputValue в Caliban, и Caliban предоставляет Encoder для Circe. Однако вы, похоже, используете авто-деривацию Circe generi c, которая не получает Encoder от Caliban, а вместо этого пытается получить InputValue самостоятельно, что дает неверный результат.

Я рекомендую использовать полу -автоматическое получение в circe-generi c или даже использование circe-дифференцирования, которое правильно подберет Encoder Caliban. Пример с circe-generi c:

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)

дает ожидаемое JSON:

{
  "query" : "query($origin: String){\n  characters(origin: $origin) {\n    name\n    nicknames\n    origin\n  }\n}",
  "operationName" : null,
  "variables" : {
    "origin" : "EARTH"
  }
}
...