玩框架过滤器,修改JSON请求和响应 [英] Play framework filter that modifies json request and response
问题描述
- (例如,用于POST,PUT和PATCH)
打印并修改传出的json响应正文和http标题
- 修改示例可以是在请求和响应主体中注入/替换一些标记字符串,例如,
- REQUEST Json:{'a':'REPLACE_ME','b':'REPLACE_ME_TOO','c': 'something'}
- 回复Json:{'A':'REPLACE_ME','Bb':'REPLACE_ME_TOO','C':'anything'}
import play.api.Logger
import play.api .mvc._
import play.api.libs.concurrent.Execution.Implicits.defaultContext
对象LoggingFilter扩展EssentialFilter {
def apply(nextFilter:EssentialAction)= new EssentialAction {
def apply(requestHeader:RequestHeader)= {
val startTime = System.currentTimeMillis
nextFilter(requestHeader).map {result =>
val endTime = System.currentTimeMillis $ b $ val requestTime = endTime - startTime
Logger.info(s$ {requestHeader.method} $ {requestHeader.uri}+
s (Request-Time - > requestTime.toString)
}
} $ b $ result.withHeaders b
$ b $ p $到目前为止我已经尝试了下面的解决方案,这个解决方案显然是丑陋而残酷的,因为它包含阻塞的呼叫和隐蔽的操作符。我仍然不知道如何重新注入修改后的请求主体。 (所提供的解决方案包含来自 2 的代码和3 。) import play.api.libs.iteratee._
import play.api.mvc._
import scala.concurrent.ExecutionContext.Implicits.global
import scala .concurrent。{Await,Future}
import scala.concurrent.duration.Duration
$ b $ class ReqResFilter extends EssentialFilter {
def apply(next:EssentialAction)= new EssentialAction {
def apply(requestHeader:RequestHeader):Iteratee [Array [Byte],Result] = {
modifyRequest(next,requestHeader).map {result => (字节),字符串] = Enumeratee.map [数组[字节]] {字节=> new String(bytes)}
$ b $ def modifyRequest(nextA:EssentialAction,request:RequestHeader):Iteratee [Array [Byte],Result] = {
def step(body: Array [Byte],nextI:Iteratee [Array [Byte],Result])(i:Input [Array [Byte]]):
Iteratee [Array [Byte],Result] = i match {
case Input.EOF =>
val requestBody = new String(body,utf-8)
val modRequestBody = requestBody.replaceAll(REPLACE_ME,1224)
println(smodifyRequest :: Here请求体$ {modRequestBody})
Iteratee.flatten(nextI.feed(Input.EOF))
case Input.Empty =>
Cont [Array [Byte],Result](step(body,nextI)_)
case Input.El(e)=>
val curBody = Array.concat(body,e)
Cont [Array [Byte],Result](step(curBody,Iteratee.flatten(nextI.feed(Input.El(e)))) _)
$ b $ val nextIteratee:Iteratee [Array [Byte],Result] = nextA(request)
Cont [Array [Byte],Result]( i => step(Array(),nextIteratee)(i))
}
def modifyResponse(result:Result):Result = {
responseBodyFuture:Future [String ] = result.body |>>> bytesToString&>> Iteratee.consume [String]()
val responseBody = Await.result(responseBodyFuture,Duration.Inf)
val modResponseBody = responseBody.replaceAll(REPLACE_ME,1224)
println (New-Header - >1234)$(responseResponse ::这是响应正文$ {modResponseBody})
新结果(result.header,Enumerator(modResponseBody.getBytes) b
$ b $ / code $ / pre
解决方案
有没有解决办法张贴在这里让我添加一个解决方案。为了使它工作,我重写了modifyRequest()中的step(),如下所示:
def step(body:Array [Byte] ,nextI:Iteratee [Array [Byte],Result])(i:Input [Array [Byte]]):
Iteratee [Array [Byte],Result] = i match {
case Input.EOF =>
val requestBody = new String(body,utf-8)
val modRequestBody = requestBody.replaceAll(REPLACE_ME,1224)
println(smodifyRequest :: Here请求体$ {modRequestBody})
Iteratee.flatten(nextI.feed(Input.El(modRequestBody.getBytes)))
case Input.Empty =>
Cont [Array [Byte],Result](step(body,nextI)_)
case Input.El(e)=>
val curBody = Array.concat(body,e)
Cont [Array [Byte],Result](step(curBody,nextI)_)
}
这个变化在缓冲传入的请求时仍然是阻塞的。如果有人有更好的解决方案,请发表。谢谢。
I'll appreciate if someone can throw pointers on how to modify the following play framework logging filter (ref. play filters) to achieve the following:
- Print and modify the incoming json request body and http headers (e.g., for POST, PUT, & PATCH)
- Print and modify the outgoing json response body and http headers
- A modification example can be injecting/replacing some token strings in the request and response body, e.g,
- REQUEST Json: {'a': 'REPLACE_ME', 'b': 'REPLACE_ME_TOO', 'c':'something'}
- RESPONSE Json: {'A': 'REPLACE_ME', 'Bb': 'REPLACE_ME_TOO', 'C':'anything'}
import play.api.Logger
import play.api.mvc._
import play.api.libs.concurrent.Execution.Implicits.defaultContext
object LoggingFilter extends EssentialFilter {
def apply(nextFilter: EssentialAction) = new EssentialAction {
def apply(requestHeader: RequestHeader) = {
val startTime = System.currentTimeMillis
nextFilter(requestHeader).map { result =>
val endTime = System.currentTimeMillis
val requestTime = endTime - startTime
Logger.info(s"${requestHeader.method} ${requestHeader.uri}" +
s" took ${requestTime}ms and returned ${result.header.status}")
result.withHeaders("Request-Time" -> requestTime.toString)
}
}
}
}
So far I have tried the following solution which is clearly ugly and brutal as it contains blocking calls and cryptic operators. I am still not sure how to re-inject the modified request body. (The presented solution incorporates code from 2 and 3.)
import play.api.libs.iteratee._
import play.api.mvc._
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.{Await, Future}
import scala.concurrent.duration.Duration
class ReqResFilter extends EssentialFilter {
def apply(next: EssentialAction) = new EssentialAction {
def apply(requestHeader: RequestHeader): Iteratee[Array[Byte], Result] = {
modifyRequest(next, requestHeader).map { result => modifyResponse(result)}
}
}
def bytesToString: Enumeratee[Array[Byte], String] = Enumeratee.map[Array[Byte]] { bytes => new String(bytes)}
def modifyRequest(nextA: EssentialAction, request: RequestHeader): Iteratee[Array[Byte], Result] = {
def step(body: Array[Byte], nextI: Iteratee[Array[Byte], Result])(i: Input[Array[Byte]]):
Iteratee[Array[Byte], Result] = i match {
case Input.EOF =>
val requestBody = new String(body, "utf-8")
val modRequestBody = requestBody.replaceAll("REPLACE_ME", "1224")
println(s"modifyRequest:: Here is the request body ${modRequestBody}")
Iteratee.flatten(nextI.feed(Input.EOF))
case Input.Empty =>
Cont[Array[Byte], Result](step(body, nextI) _)
case Input.El(e) =>
val curBody = Array.concat(body, e)
Cont[Array[Byte], Result](step(curBody, Iteratee.flatten(nextI.feed(Input.El(e)))) _)
}
val nextIteratee: Iteratee[Array[Byte], Result] = nextA(request)
Cont[Array[Byte], Result](i => step(Array(), nextIteratee)(i))
}
def modifyResponse(result: Result): Result = {
val responseBodyFuture: Future[String] = result.body |>>> bytesToString &>> Iteratee.consume[String]()
val responseBody = Await.result(responseBodyFuture, Duration.Inf)
val modResponseBody = responseBody.replaceAll("REPLACE_ME", "1224")
println(s"modifyResponse:: Here is the response body ${modResponseBody}")
new Result(result.header, Enumerator(modResponseBody.getBytes)).withHeaders("New-Header" -> "1234")
}
}
解决方案 Well since there are no solutions posted here let me add one solution. To make it work, I rewrote step() in modifyRequest() as follows:
def step(body: Array[Byte], nextI: Iteratee[Array[Byte], Result])(i: Input[Array[Byte]]):
Iteratee[Array[Byte], Result] = i match {
case Input.EOF =>
val requestBody = new String(body, "utf-8")
val modRequestBody = requestBody.replaceAll("REPLACE_ME", "1224")
println(s"modifyRequest:: Here is the request body ${modRequestBody}")
Iteratee.flatten(nextI.feed(Input.El(modRequestBody.getBytes)))
case Input.Empty =>
Cont[Array[Byte], Result](step(body, nextI) _)
case Input.El(e) =>
val curBody = Array.concat(body, e)
Cont[Array[Byte], Result](step(curBody, nextI) _)
}
The change is still blocking in nature as it buffers the incoming request. If someone has better solution please do post. Thanks.
这篇关于玩框架过滤器,修改JSON请求和响应的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!