Подтвердить что ты не робот

Параметры запроса для запросов GET с использованием Akka HTTP (формально известного как Spray)

Одной из особенностей Akka HTTP (формально известной как Spray) является ее способность автоматически маршалировать и развязывать данные взад и вперед от json до классов case и т.д. У меня был успех, чтобы заставить это работать хорошо.

В настоящий момент я пытаюсь создать клиент HTTP, который выполняет запрос GET с параметрами запроса. Код теперь выглядит следующим образом:

val httpResponse: Future[HttpResponse] =
  Http().singleRequest(HttpRequest(
    uri = s"""http://${config.getString("http.serverHost")}:${config.getInt("http.port")}/""" +
          s"query?seq=${seq}" +
          s"&max-mismatches=${maxMismatches}" +
          s"&pam-policy=${pamPolicy}"))

Ну, это не так красиво. Было бы неплохо, если бы я мог просто передать класс case, содержащий параметры запроса, и заставить Akka HTTP автоматически генерировать параметры запроса, вроде как для json. (Кроме того, серверная сторона Akka HTTP имеет несколько элегантный способ анализа параметров запроса GET, поэтому можно было бы подумать, что у него также будет несколько элегантный способ их создания.)

Я хотел бы сделать что-то вроде следующего:

val httpResponse: Future[HttpResponse] =
  Http().singleRequest(HttpRequest(
    uri = s"""http://${config.getString("http.serverHost")}:${config.getInt("http.port")}/query""",
    entity = QueryParams(seq = seq, maxMismatches = maxMismatches, pamPolicy = pamPolicy)))

Только это не работает.

Я хочу что-то сделать с помощью Akka HTTP? Или мне просто нужно делать что-то старомодным? I.e, явным образом генерирую параметры запроса, как и в первом блоке кода выше.

(Я знаю, что если бы я изменил это с GET на POST, я мог бы, вероятно, заставить его работать больше, как хотелось бы, чтобы он работал, с тех пор я могу получить содержимое запроса POST, автоматически преобразованного от класса case до json, но я действительно не хочу этого делать здесь.)

4b9b3361

Ответ 1

Вы можете использовать класс Uri, чтобы делать то, что хотите. Он предлагает несколько способов получить набор параметров в строку запроса с помощью метода withQuery. Например, вы можете сделать что-то вроде этого:

val params = Map("foo" -> "bar", "hello" -> "world")
HttpRequest(Uri(hostAndPath).withQuery(params))

или

HttpRequest(Uri(hostAndPath).withQuery(("foo" -> "bar"), ("hello" -> "world")))

Ответ 2

Очевидно, это можно сделать, изменив расширение возможностей Akka HTTP, но для чего вам нужно (просто более аккуратный способ построения строки запроса), вы можете сделать это с помощью scala fun:

type QueryParams = Map[String, String]

object QueryParams {

  def apply(tuples: (String, String)*): QueryParams = Map(tuples:_*)
}

implicit class QueryParamExtensions(q: QueryParams) {

  def toQueryString = "?"+q.map{
    case (key,value) => s"$key=$value" //Need to do URL escaping here?
  }.mkString("&")
}

implicit class StringQueryExtensions(url: String) {
  def withParams(q: QueryParams) =
    url + q.toQueryString
}

val params = QueryParams(
  "abc" -> "def",
  "xyz" -> "qrs"
)

params.toQueryString // gives ?abc=def&xyz=qrs

"http://www.google.com".withParams(params) // gives http://www.google.com?abc=def&xyz=qrs