2

Web アプリケーションのクライアント側から、サードパーティ API の単なるラッパーであるサーバー側ルートにヒットしました。ディスパッチを使用して、サーバー側のリクエストが正確なヘッダーとサードパーティ API の応答をクライアント側の AJAX 呼び出しに返すようにしようとしています。

私がこれを行うとき:

val req = host("third-pary.api.com, 80)
val post = req.as("user", "pass") / "route" << Map("key" -> "akey", "val" -> "aval")
Http(post > as.String)

AJAX 呼び出しに応答が返されるのを常に確認し200ます (予想通り)。構文が使用されているのを見たことがありますが、それは正確な応答とヘッダーに過ぎないため、Either実際にはもっとです。Anyこれはどのように書かれますか?

サーバー側で Scalatra を使用しているため、ローカル ルートは次のとおりです。

post("/route") {

}

編集:

これは、私が遊んでいる推奨されるどちらの一致例ですが、match構文は意味がありません-エラーがあっても気にしません。エラーを返したいだけです。また、このメソッドで返される BODY を取得できないようです。

val asHeaders = as.Response { response =>
  println("BODY: " + response.getResponseBody())
  scala.collection.JavaConverters.mapAsScalaMapConverter(
    response.getHeaders).asScala.toMap.mapValues(_.asScala.toList)
}

val response: Either[Throwable, Map[String, List[String]]] =
  Http(post > asHeaders).either()

response match {
  case Left(wrong) =>
    println("Left: " + wrong.getMessage())
    // return Action with header + body
  case Right(good) =>
    println("Right: " + good)
    // return Action with header + body
}

理想的には、ソリューションは Scalatra を返しますActionResult(responseStatus(status, reason), body, headers)

4

2 に答える 2

5

実際、Dispatch の使用中に応答ヘッダーを取得するのは非常に簡単です。たとえば、0.9.4 の場合:

import dispatch._
import scala.collection.JavaConverters._

val headers: java.util.Map[String, java.util.List[String]] = Http(
   url("http://www.google.com")
)().getHeaders

そして今、例えば:

scala> headers.asScala.mapValues(_.asScala).foreach {
     |   case (k, v) => println(k + ": " + v)
     | }
X-Frame-Options: Buffer(SAMEORIGIN)
Transfer-Encoding: Buffer(chunked)
Date: Buffer(Fri, 30 Nov 2012 20:42:45 GMT)
...

これを頻繁に行う場合は、次のようにカプセル化することをお勧めします。

val asHeaders = as.Response { response =>
  scala.collection.JavaConverters.mapAsScalaMapConverter(
    response.getHeaders
  ).asScala.toMap.mapValues(_.asScala.toList)
}

これで、次のように記述できます。

val response: Either[Throwable, Map[String, List[String]]] =
  Http(url("http://www.google.com") OK asHeaders).either()

また、エラー チェック、素敵な不変コレクションなどがあります。

于 2012-11-30T20:54:51.403 に答える
0

API への失敗したリクエストのレスポンス本文が必要だったので、次のソリューションを考え出しました。

andを使用して独自のApiHttpErrorクラスを定義します(本文用): codebody

case class ApiHttpError(code: Int, body: String)
  extends Exception("Unexpected response status: %d".format(code))

OkWithBodyHandlerのソースで使用されているものと同様に定義しdisplatchます。

class OkWithBodyHandler[T](f: Response => T) extends AsyncCompletionHandler[T] {
  def onCompleted(response: Response) = {
    if (response.getStatusCode / 100 == 2) {
      f(response)
    } else {
      throw ApiHttpError(response.getStatusCode, response.getResponseBody)
    }
  }
}

ここで、スローして例外を発生させる可能性のあるコード ( の呼び出し ) への呼び出しの近くで、 (ソース コードと同様に) にオーバーライドをAPI追加し、 onを呼び出します。implicitToupleBuilderOkWithBodyrequest

class MyApiService {
  implicit class MyRequestHandlerTupleBuilder(req: Req) {
    def OKWithBody[T](f: Response => T) =
      (req.toRequest, new OkWithBodyHandler(f))
  }

  def callApi(request: Req) = {
    Http(request OKWithBody as.String).either
  }
}

これからは、取得eitherすると[Throwable, String](usingが返されas.String)、 theThrowableはおよび.ApiHttpErrorcodebody

それが役に立ったことを願っています。

于 2015-02-02T09:01:08.393 に答える