播放2.5.x如何修改响应的内容标题,即没有缓存?

时间:2016-12-26 11:05:47

标签: scala playframework http-headers httpresponse deadbolt-2

使用Scala和Play 2.5.10我为合成实现了以下可重用的操作,目的是通过更改响应头来禁用浏览器中的缓存:

import play.api.http.HeaderNames
import play.api.mvc._

import scala.concurrent.Future
import scala.util.{Failure, Success}
import scala.concurrent.ExecutionContext.Implicits.global

case class NoCache[A](action: Action[A]) extends Action[A] with HeaderNames {
  def apply(request: Request[A]): Future[Result] = {
    action(request).andThen {
      case Success(result) => result.withHeaders(
        (CACHE_CONTROL -> "no-cache, no-store, must-revalidate"),
        (PRAGMA -> "no-cache"),
        (EXPIRES -> "0")
      )
      case Failure(result) => result
    }
  }

  lazy val parser = action.parser
}

然后我在我的控制器动作实现中重用它:

def link = NoCache {
  deadbolt.SubjectPresent()() { implicit request =>
    Future {
      Ok(views.html.account.link(userService, auth))
    }
  }
}

我断开了NoCache实现并且它被正确执行,但是,使用Web Developer Firefox plugin来监控网络流量我看到响应头不包含"没有缓存&# 34;修改......我做错了什么?

1 个答案:

答案 0 :(得分:1)

您的代码存在问题

问题在于<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"> <jsp-property-group> <url-pattern>*.jsp</url-pattern> <el-ignored>true</el-ignored> <scripting-invalid>true</scripting-invalid> </jsp-property-group> </web-app> andThen会丢弃返回值。因此,带有新标题的已转换andThen将被丢弃。

删除result并将其设为andThen

map用于在调用它的未来完成后运行副作用计算。

andThen的计算返回Future,其结果与原始未来相同,并丢弃andThen内的计算的返回类型。

以下是标准库中的andThen的实现。

andThen

更正您的代码

 def andThen[U](pf: PartialFunction[Try[T], U])(implicit executor: ExecutionContext): Future[T] = {
    val p = Promise[T]()
    onComplete {
      case r => try pf.applyOrElse[Try[T], Any](r, Predef.conforms[Try[T]]) finally p complete r
    }
    p.future
  }

其他方法

您可以使用播放过滤器case class NoCache[A](action: Action[A]) extends Action[A] with HeaderNames { def apply(request: Request[A]): Future[Result] = { action(request).map { result => result.withHeaders( (CACHE_CONTROL -> "no-cache, no-store, must-revalidate"), (PRAGMA -> "no-cache"), (EXPIRES -> "0") ) } } lazy val parser = action.parser } 来更改标题,也可以用于执行一些预处理和后期处理工作。

您可以通过检查请求的uri来仅定位特定路线。

Filter

在上面的import akka.stream.Materializer import com.google.inject.{Inject, Singleton} import play.api.http.DefaultHttpFilters import play.api.mvc.{Filter, RequestHeader, Result} import play.mvc.Http.HeaderNames import scala.concurrent.Future @Singleton class Filters @Inject() (fooFilter: FooFilter) extends DefaultHttpFilters(fooFilter) {} @Singleton class FooFilter @Inject() (implicit override val mat: Materializer) extends Filter { override def apply(f: (RequestHeader) => Future[Result])(rh: RequestHeader): Future[Result] = { f(rh).map { result => if (rh.uri.startsWith("/foo")) result.withHeaders(HeaderNames.CACHE_CONTROL -> "no-cache") else result } } } 路由示例中,将设置cache_control,对于其他路由,将传播相同的头。

注意在播放应用的根文件夹中创建过滤器,如果没有将过滤器添加到application.conf

永远不要在过滤器内运行繁重的运行计算,使过滤器尽可能轻。