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)

我总是看到200返回到 AJAX 调用的响应(有点预期)。我已经看到使用的Either语法,但我真的更像一个Any,因为它只是确切的响应和标题。这要怎么写?

我应该提到我在服务器端使用 Scalatra,所以本地路由是:

post("/route") {

}

编辑:

这是我正在使用的建议的 Either 匹配示例,但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)的调用附近,将implicit覆盖添加到ToupleBuilder(再次类似于源代码)并OkWithBody调用request

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

从现在开始,fetchingeither会给你[Throwable, String](using as.String), and the Throwableis our ApiHttpErrorwith codeand body.

希望它有所帮助。

于 2015-02-02T09:01:08.393 回答