【问题标题】:Query parameters for GET requests using Akka HTTP (formally known as Spray)使用 Akka HTTP(正式名称为 Spray)查询 GET 请求的参数
【发布时间】:2015-08-11 22:56:50
【问题描述】:

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,但我真的不希望在这里这样做。)

【问题讨论】:

    标签: akka spray akka-http


    【解决方案1】:

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

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

    或者

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

    【讨论】:

    • 使用这个方法的好处是使用这个方法会自动转义。
    • 使用 Akka-http 2.4.8,这似乎需要 Query 包装:.withQuery(Query(params)))
    • 这应该在文档中
    • @coolboyjules 完全正确。这个答案很好,但遗憾的是,在登陆这里之前必须在互联网上进行大量搜索。这属于文档。在我的待办事项清单上——因为文档代码是开源的。
    • 它现在是文档的一部分 :) doc.akka.io/docs/akka-http/10.2/client-side/… 链接到此处的具体示例 doc.akka.io/docs/akka-http/10.2/common/…
    【解决方案2】:

    显然,这可以通过更改 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
    

    【讨论】:

      猜你喜欢
      • 2014-09-30
      • 1970-01-01
      • 2019-02-25
      • 2022-12-05
      • 2021-09-07
      • 2023-03-18
      • 2015-02-03
      • 2020-10-20
      • 2020-12-02
      相关资源
      最近更新 更多