1
如何使用Play Framework執行完整代理?Play Framework中的代理請求
我想保持請求和響應的標題和正文不變。基本上,一個透明的代理層到客戶端和服務器。
注:我有一些工作。當SO允許我時,會發布它。
如何使用Play Framework執行完整代理?Play Framework中的代理請求
我想保持請求和響應的標題和正文不變。基本上,一個透明的代理層到客戶端和服務器。
注:我有一些工作。當SO允許我時,會發布它。
這就是我最終得到的。
隨着我(不全面)的測試,這適用於各種身體類型的所有方法。
請注意我使用_.head
。我還沒有探討爲什麼標題的類型爲Map[String, Seq[String]]
。我可能會丟棄重複的標題內容(例如,在標題中具有多於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)
隨意提出修改建議。