我想捕获我的服务器将与响应标头一起发送到浏览器的响应标头。经过检查,我可以看到:
但是,当我尝试使用我的过滤器中间件来利用这些内容时:
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):_*)
您的过滤器需要位于列表的开头。应用过滤器的代码以与列表相同的顺序包装它们,因此基本上扩展为:
firstFilter.apply(secondFilter.apply(thirdFilter.apply(action))))
因此,第一个过滤器是最外层的过滤器,因此当它收到响应时,它将从所有内部过滤器中获取响应,并使用所有内部过滤器设置的标头。