17

Akka HTTP(以前称为 Spray)的特性之一是它能够自动地从 json 到 case 类等中来回编组和解组数据。我已经成功地让它运行良好。

目前,我正在尝试制作一个使用查询参数执行 GET 请求的 HTTP 客户端。目前的代码如下所示:

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}"))

好吧,那不是那么漂亮。如果我可以传入一个包含查询参数的案例类,并让 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 以某种方式实现吗?还是我只需要以老式的方式做事?即,显式生成查询参数,就像我在上面的第一个代码块中所做的那样。

(我知道如果我要将它从 GET 更改为 POST,我可能会让它更像我希望它工作的那样工作,因为那时我可以从一个案例中自动转换 POST 请求的内容类到 json,但我真的不想在这里这样做。)

4

2 回答 2

30

你可以利用这个Uri类来做你想做的事。它提供了多种方法来使用该withQuery方法将一组参数放入查询字符串中。例如,您可以执行以下操作:

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

或者

HttpRequest(Uri(hostAndPath).withQuery(("foo" -> "bar"), ("hello" -> "world")))
于 2015-08-11T10:50:50.067 回答
0

显然,这可以通过更改 Akka HTTP 的扩展功能来完成,但是对于您需要的(只是构建查询字符串的一种更简洁的方式),您可以通过一些 scala 乐趣来做到这一点:

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
于 2015-08-11T08:47:16.800 回答