web-dev-qa-db-ja.com

Akka HTTP(正式にはSprayと呼ばれます)を使用したGETリクエストのクエリパラメータ

Akka HTTP(正式にはSprayと呼ばれます)の機能の1つは、jsonからケースクラスなどにデータを自動的にマーシャリングおよびアンマーシャリングする機能です。これをうまく機能させることに成功しました。

現時点では、クエリパラメータを使用して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}"))

まあ、それはそれほどきれいではありません。クエリパラメータを含むcaseクラスを渡すだけで、jsonの場合と同じように、AkkaHTTPにクエリパラメータを自動的に生成させることができれば便利です。 (また、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に変換されますが、ここでは実際にはやりたくありません。)

16
Douglas

Uriクラスを活用して、やりたいことを実行できます。 withQueryメソッドを使用して、一連のパラメータをクエリ文字列に取り込む複数の方法を提供します。たとえば、次のようなことができます。

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

または

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

明らかに、これは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
1
mattinbits