如何在 Play Framework 中为 WebSocket 请求添加过滤器
How do I add filters for WebSocket requests in Play Framework
使用 Play 2.5.3,我有这个过滤器设置:
@Singleton
class Filters @Inject() (
env: Environment,
postRequestLoggingFilter: PostRequestLoggingFilter) extends HttpFilters {
override val filters = {
Seq(postRequestLoggingFilter)
}
}
这对于常规的 HTTP Web 请求非常有效,但不会触发 WebSocket 路由 (ws://),例如:
class Controller3 @Inject() (implicit system: ActorSystem, materializer: Materializer) extends play.api.mvc.Controller {
def socket = WebSocket.acceptOrResult[String, String] { request =>
...
如何将这种路由类型包含在我的过滤器中,或者是否有其他机制可以拦截这种类型的请求?
在花了一些时间研究这个问题之后,过滤器系统当前的工作方式并不适合应用于 WebSocket 请求。
问题是过滤器使用采用
的应用方法
nextFilter: RequestHeader => Future[Result]
其中 WebSocket 函数采用
f: RequestHeader => Future[Either[Result, Flow[In, Out, _]]]
所以通过过滤器系统传递 WebSocket 结果并没有真正起作用。
然而,就我而言,我主要对日志记录过滤器感兴趣。因此,作为解决方法,我创建了 acceptOrResult
的自定义版本,如下所示:
def acceptOrResult[TIn, TOut](f: RequestHeader => Future[Either[Result, Flow[TIn, TOut, _]]])(implicit transformer: MessageFlowTransformer[TIn, TOut], materializer: Materializer, ec: ExecutionContext): WebSocket = {
WebSocket { request =>
f(request).map { fResult =>
PostRequestLoggingFilter.apply(request,fResult.left.getOrElse(Ok))
fResult.right.map(transformer.transform)
}
}
}
我需要将 PostRequestLoggingFilter
的逻辑分解到它的伴随对象的 apply 方法中,这样上面的方法才能起作用。
如果WebSocket
请求是Left
,我们有一个Result
;如果它是 Right
那么我只传递一个 Ok
结果。这可以应用于其他过滤器,只要您不介意它们会 运行 在 WebSocket 请求之后。
使用 Play 2.5.3,我有这个过滤器设置:
@Singleton
class Filters @Inject() (
env: Environment,
postRequestLoggingFilter: PostRequestLoggingFilter) extends HttpFilters {
override val filters = {
Seq(postRequestLoggingFilter)
}
}
这对于常规的 HTTP Web 请求非常有效,但不会触发 WebSocket 路由 (ws://),例如:
class Controller3 @Inject() (implicit system: ActorSystem, materializer: Materializer) extends play.api.mvc.Controller {
def socket = WebSocket.acceptOrResult[String, String] { request =>
...
如何将这种路由类型包含在我的过滤器中,或者是否有其他机制可以拦截这种类型的请求?
在花了一些时间研究这个问题之后,过滤器系统当前的工作方式并不适合应用于 WebSocket 请求。
问题是过滤器使用采用
的应用方法nextFilter: RequestHeader => Future[Result]
其中 WebSocket 函数采用
f: RequestHeader => Future[Either[Result, Flow[In, Out, _]]]
所以通过过滤器系统传递 WebSocket 结果并没有真正起作用。
然而,就我而言,我主要对日志记录过滤器感兴趣。因此,作为解决方法,我创建了 acceptOrResult
的自定义版本,如下所示:
def acceptOrResult[TIn, TOut](f: RequestHeader => Future[Either[Result, Flow[TIn, TOut, _]]])(implicit transformer: MessageFlowTransformer[TIn, TOut], materializer: Materializer, ec: ExecutionContext): WebSocket = {
WebSocket { request =>
f(request).map { fResult =>
PostRequestLoggingFilter.apply(request,fResult.left.getOrElse(Ok))
fResult.right.map(transformer.transform)
}
}
}
我需要将 PostRequestLoggingFilter
的逻辑分解到它的伴随对象的 apply 方法中,这样上面的方法才能起作用。
如果WebSocket
请求是Left
,我们有一个Result
;如果它是 Right
那么我只传递一个 Ok
结果。这可以应用于其他过滤器,只要您不介意它们会 运行 在 WebSocket 请求之后。