scala - 在 Play 框架中代理请求

标签 scala playframework proxy

如何使用 Play Framework 进行完整代理?

我想保持请求和响应的 header 和正文完好无损。基本上,对客户端和服务器来说都是透明的代理层。

注意:我有一些工作。当允许时我会发布它。

最佳答案

这就是我最终得到的结果。

根据我的(不全面)测试,这适用于各种 body 类型的所有方法。

请注意我对 _.head 的使用。我还没有深入研究为什么 header 具有 Map[String, Seq[String]] 类型。我可能会删除重复的 header 内容(例如, header 中的内容超过 Content-Type)。也许将 Seq[String]; 结合起来是更好的方法。

import play.api.libs.ws._
import play.api.libs.iteratee.Enumerator
import play.api.mvc._

def proxy(proxyUrl: String) = Action.async(BodyParsers.parse.raw) { request =>
  // filter out the Host and potentially any other header we don't want
  val headers: Seq[(String, String)] = request.headers.toSimpleMap.toSeq.filter {
    case (headerStr, _) if headerStr != "Host" => true
    case _ => false
  }
  val wsRequestBase: WSRequestHolder = WS.url(s"http://localhost:9000/$proxyUrl") // set the proxy path
    .withMethod(request.method) // set our HTTP method
    .withHeaders(headers : _*) // Set our headers, function takes var args so we need to "explode" the Seq to var args
    .withQueryString(request.queryString.mapValues(_.head).toSeq: _*) // similarly for query strings
  // depending on whether we have a body, append it in our request
  val wsRequest: WSRequestHolder = request.body.asBytes() match {
    case Some(bytes) => wsRequestBase.withBody(bytes)
    case None => wsRequestBase
  }
  wsRequest
    .stream() // send the request. We want to process the response body as a stream
    .map { case (responseHeader: WSResponseHeaders, bodyStream: Enumerator[Array[Byte]]) => // we want to read the raw bytes for the body
      // Content stream is an enumerator. It's a 'stream' that generates Array[Byte]
      new Result(
        new ResponseHeader(responseHeader.status),
        bodyStream
      )
      .withHeaders(responseHeader.headers.mapValues(_.head).toSeq: _*)
    }
}

routes 文件条目将如下所示:

GET     /proxy/*proxyUrl                   @controllers.Application.proxy(proxyUrl: String)

您将需要其他行来支持其他方法(例如 POST)

欢迎提出修改建议。

关于scala - 在 Play 框架中代理请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34408359/

相关文章:

playframework - 在编译和集群服务器上退出securesocial

postgresql - ODBC/JDBC 代理到 Postgresql

scala - Spray.io、光滑、sqlite3 : no suitable driver found

scala - 如何将一个偏函数转换为另一个偏函数?

java - 如何在Play框架应用程序中编写junit测试用例

java - Play Framework 依赖注入(inject)不起作用

http - 检查来自与 Connectify 连接的设备的流量

javascript - 在转发到代理目标并将响应发送回客户端之前编辑 POST 参数

调用 copy() 时父特性的 Scala Case 类复制成员

java - 如何在 Debian 上部署 Play 2.0 应用程序?