繁体   English   中英

播放框架过滤器,可修改json请求和响应

[英]Play framework filter that modifies json request and response

如果有人可以提出如何修改以下播放框架日志记录过滤器(参考play过滤器 )以实现以下目标的方法,我将不胜感激:

  • 打印和修改传入的json请求正文和http标头(例如,用于POST,PUT和PATCH)
  • 打印并修改传出的json响应主体和http标头
  • 修改示例可以是在请求和响应主体中注入/替换一些令牌字符串,例如,
  • 请求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

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

到目前为止,我已经尝试了以下解决方案,该解决方案显然丑陋且残酷,因为它包含阻塞调用和隐式运算符。 我仍然不确定如何重新注入修改后的请求正文。 (提出的解决方案合并了23中的代码。)

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

好吧,因为这里没有发布解决方案,让我添加一个解决方案。 为了使其正常工作,我将step()重写为ModifyRequest(),如下所示:

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

由于更改会缓冲传入的请求,因此更改本质上仍处于阻塞状态。 如果有人有更好的解决方案,请发表。 谢谢。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM