玩框架过滤器,修改JSON请求和响应 [英] Play framework filter that modifies json request and response

查看:278
本文介绍了玩框架过滤器,修改JSON请求和响应的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我会很感激,如果有人可以抛出如何修改以下的播放框架日志过滤器(参考 play filters )来实现以下功能:


  • (例如,用于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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆