使用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;修改......我做错了什么?
答案 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
永远不要在过滤器内运行繁重的运行计算,使过滤器尽可能轻。