如何在Play Framework中为WebSocket请求添加过滤器

时间:2016-07-05 16:21:55

标签: scala websocket playframework-2.0

使用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 =>
        ...

如何在我的过滤器中包含此路由类型,或者是否有其他机制来拦截此类请求?

1 个答案:

答案 0 :(得分:2)

花了一些时间研究这个,过滤系统目前的工作方式,它不适合应用于WebSocket请求。

问题是过滤器使用带有

的apply方法
nextFilter: RequestHeader => Future[Result]

其中WebSocket函数采用

f: RequestHeader => Future[Either[Result, Flow[In, Out, _]]]

因此,通过Filter系统传递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中的逻辑分解为其伴随对象的应用方法,以便上述功能正常运行。

如果WebSocket请求为Left,我们会有Result;如果它是Right,那么我只传递Ok结果。这可以应用于其他过滤器,只要您不必在 WebSocket请求之后运行这一事实。