Scala Play 在过滤器中间件中获取响应标头?

问题描述 投票:0回答:1

我想捕获我的服务器将与响应标头一起发送到浏览器的响应标头。经过检查,我可以看到:

但是,当我尝试使用我的过滤器中间件来利用这些内容时:

class CustomFilter @Inject()(implicit val mat: Materializer, ec: ExecutionContext) extends Filter {
  private val logger = Logger(this.getClass)

  private def getRequestContext(ctx: RequestContext):String = {
    val RequestContext(userAgent, remoteAddress) = ctx
    // Log request context information based on availability of remoteAddress, appToken and appVersion
    s"NRS Request [User-Agent=$userAgent] [Remote-Address=$remoteAddress]"
  }

  private def getResponseContext(resCtx: ResponseContext): String = {
    val ResponseContext(duration, statusCode, appToken, appVersion, requestID, clientID, redirect, via) = resCtx
    s"NRS Response [DurationInMs=$duration] [Status=$statusCode] [App-Token=$appToken] [App-Version=$appVersion] [Request-ID=$requestID] [Client-ID=$clientID] [Redirect=$redirect] [Via=$via]"
  }


  private def getCompleteContext(reqCtx: RequestContext, resCtx: ResponseContext):String =
    s"{{${getRequestContext(reqCtx)}::${getResponseContext(resCtx)}}}"

  override def apply(nextFilter: RequestHeader => Future[Result])(requestHeader: RequestHeader): Future[Result] = {
    val startTime = System.currentTimeMillis()

    // Extract request context information
    val userAgent = requestHeader.headers.get("User-Agent").getOrElse("")
    val remoteAddress = requestHeader.headers.get("Remote-Address")

    nextFilter(requestHeader).flatMap { result =>
      val endTime = System.currentTimeMillis()
      val duration = endTime - startTime
      val status = result.header.status
      val appToken = result.header.headers.get("X-App-Token")
      val appVersion = result.header.headers.get("X-App-Version")
      val requestID = result.header.headers.get("X-Request-ID")
      val clientID = result.header.headers.get("X-Client-ID")
      val redirect = result.header.headers.get("X-Redirect")
      val via = result.header.headers.get("Via")

      println(s"""Headers: ${result.header.headers.mkString(",")}::${requestHeader.headers.headers.mkString(",")}""")

      if (userAgent.nonEmpty) {
        logger.warn(
          getCompleteContext(
            RequestContext(userAgent, remoteAddress),
            ResponseContext(duration, status, appToken, appVersion, requestID, clientID, redirect, via)
          )
        )
      }

      Future.successful(result)
    } recoverWith {
      case e: Throwable =>
        val endTime = System.currentTimeMillis()
        val duration = endTime - startTime

        if (userAgent.nonEmpty) {
          logger.warn(getCompleteContext(RequestContext(userAgent, remoteAddress), ResponseContext(duration, 500, None, None, None, None, None, None)))
        }

        // Propagate the exception
        Future.failed(e)
    }
  }
}

不幸的是,我无法在我的中间件中看到这些响应标头。有人可以帮助我理解我做错了什么吗?

我可以设置新标题,但无法获取旧标题:

Future.successful(result.withHeaders("X-Request-ID-022" -> requestID.getOrElse("dvcsdf")))

我收到这些响应日志:

Response Header 121 - Access-Control-Allow-Origin: *
Response Header 121 - ETag: "XXXXXXX"

以下是我应用的常见过滤器:

class Filters @Inject()(corsFilter: CORSFilter,
                        clientIdFilter: ClientIdFilter,
                        requestIdFilter: RequestIdFilter,
                        processingTimeFilter: ProcessingTimeFilter,
                        host: HostFilter,
                        date: DateFilter,
                        head: HeadFilter,
                        gzipFilter: GzipFilter,
                        customFilter: CustomFilter
                       )
  extends DefaultHttpFilters(Seq(corsFilter, processingTimeFilter,
      clientIdFilter, requestIdFilter, host, date, head, gzipFilter,customFilter):_*)
scala playframework
1个回答
0
投票

您的过滤器需要位于列表的开头。应用过滤器的代码以与列表相同的顺序包装它们,因此基本上扩展为:

firstFilter.apply(secondFilter.apply(thirdFilter.apply(action))))

因此,第一个过滤器是最外层的过滤器,因此当它收到响应时,它将从所有内部过滤器中获取响应,并使用所有内部过滤器设置的标头。

© www.soinside.com 2019 - 2024. All rights reserved.