Play 2 - Установить заголовок для всех ответов?

Я знаю из Настройка заголовков HTTP в Play 2.0 (scala)?, чтобы вы могли настраивать заголовки ответов в каждом конкретном случае, например, Ok("hello").withHeaders(PRAGMA -> "no-cache").

Что делать, если вы хотите установить этот заголовок или несколько разных заголовков на ответы всех ваших действий? Вы не хотели бы повторять withHeaders всюду. И поскольку это больше похоже на конфигурацию на уровне приложения, вам может не потребоваться, чтобы авторы действий использовали другой синтаксис для получения заголовков (например, OkWithHeaders(...))

Теперь у меня есть базовый класс контроллера, который выглядит как

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

но это не совсем правильно. Похоже, что должно быть больше стиля AOP для определения заголовков по умолчанию и добавления их в каждый ответ.

Ответы

Ответ 1

В своем 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)
    }
  }

}

В этом случае я вызываю действие только в режиме dev, что имеет наибольшее значение для инструкции no-cache.

Ответ 2

Тема довольно старая, но с 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"
    ))
  }
}

Ответ 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

Есть слишком способы. Вы можете использовать action-composition. Затем вы должны объявить на каждом контроллере, что вы хотите установить здесь заголовок. Другой вариант - использовать GlobalSettings. Аналогичные решения для java тоже.