【问题标题】:Play 2 - Set header on all responses?播放 2 - 在所有响应上设置标题?
【发布时间】:2012-07-13 19:57:50
【问题描述】:

我从Setting HTTP headers in Play 2.0 (scala)? 了解到,您可以根据具体情况设置响应标头,例如,Ok("hello").withHeaders(PRAGMA -> "no-cache")

如果您想为所有操作的响应设置该标题或几个不同的标题怎么办?您不想到处重复withHeaders。而且由于这更像是应用程序范围的配置,您可能不希望 Action 编写者必须使用不同的语法来获取您的标头(例如 OkWithHeaders(...)

我现在拥有的是一个看起来像这样的基本 Controller 类

class ContextController extends Controller {
 ...
 def Ok(h: Html) = Results.Ok(h).withHeaders(PRAGMA -> "no-cache")
}

但这感觉不太对劲。感觉应该有更多 AOP 风格的方式来定义默认标头并将它们添加到每个响应中。

【问题讨论】:

  • 请注意,PRAGMA -> no-cache 可能不会按照您的预期工作。请参阅此链接:mnot.net/cache_docs 您可能想使用 CACHE_CONTROL 而不是 PRAGMA
  • CACHE_CONTROL -> "max-age=0" 应该这样做。

标签: scala playframework-2.0


【解决方案1】:

方法太多了。您可以使用action-composition。然后,您必须在要在此处设置的每个控制器上声明标头。另一种选择是使用GlobalSettings。 java也有类似的解决方案。

【讨论】:

  • 我看不到您可以在 GlobalSettings 中的哪个位置执行此操作,您能更具体一点吗?在我看来,您只有对请求的钩子,而不是响应。
  • 那么你可以用你自己的来包装普通的动作。然后我认为你可以访问结果对象并且你可以做到这一点。只是一个想法,因为我正在使用java。那里有包含响应的上下文。
【解决方案2】:

在您的 Global.scala 中,将每个调用都包含在一个操作中:

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

object Global extends GlobalSettings {

  def NoCache[A](action: Action[A]): Action[A] = Action(action.parser) { request =>
    action(request) match {
      case s: SimpleResult[_] => s.withHeaders(PRAGMA -> "no-cache")
      case result => result
    }
  }

  override def onRouteRequest(request: RequestHeader): Option[Handler] = {
    if (Play.isDev) {
      super.onRouteRequest(request).map {
        case action: Action[_] => NoCache(action)
        case other => other
      }
    } else {
      super.onRouteRequest(request)
    }
  }

}

在这种情况下,我只在开发模式下调用操作,这对于无缓存指令最有意义。

【讨论】:

  • 可爱,谢谢!我偶然发现了一个类似的解决方案,但是在匹配参数化类型 SimpleResult 时遇到了问题,而没有编译器关于擦除的警告。另外,请注意我上面关于 PRAGMA 用于缓存的错误的评论。
  • @MariusSoutier - 我尝试了您建议的解决方案,但在运行时,我总是得到 "other" 而不是 Action 我可以用来添加标题。 "other" 在运行时的类型是:play.core.Router$Routes$$anon$4 知道如何处理它吗?
  • 关于我之前的评论:@BobG 回答与此有关。
  • super.onRouteRequest(request) 返回的处理程序类型在 playframework 2.2 中发生了变化。可在此处找到适用于 2.2 的此代码的更新版本stackoverflow.com/questions/20533289/…
【解决方案3】:

实现细粒度控制的最简单方法是使用包装的操作。在你的情况下,它可能是这样的:

object HeaderWriter {
    def apply(f: Request[AnyContent] => SimpleResult):Action[AnyContent] = {
        Action { request =>
            f(request).withHeaders(PRAGMA -> "no-cache")
        }
    }
}

并以这种方式使用它:

def doAction = HeaderWriter { request =>
    ... do any stuff your want ...
    Ok("Thats it!")
}

【讨论】:

    【解决方案4】:

    这个话题现在已经很老了,但是在 Play 2.1 中它现在变得更加简单了。 你的Global.scala 类应该是这样的:

    import play.api._
    import play.api.mvc._
    import play.api.http.HeaderNames._
    
    /**
     * Global application settings.
     */
    object Global extends GlobalSettings {
    
      /**
       * Global action composition.
       */
      override def doFilter(action: EssentialAction): EssentialAction = EssentialAction { request =>
        action.apply(request).map(_.withHeaders(
          PRAGMA -> "no-cache"
        ))
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2015-10-18
      • 1970-01-01
      • 2015-08-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多