Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Play 2 - Set header on all responses?

I'm aware from Setting HTTP headers in Play 2.0 (scala)? that you can set response headers on a case-by-case basis by doing, for example, Ok("hello").withHeaders(PRAGMA -> "no-cache").

What if you want to set that header, or a few different headers, on responses from all your Actions? You wouldn't want to repeat the withHeaders everywhere. And since this is more like an application-wide configuration, you might not want Action writers to have to use a different syntax to get your headers (e.g. OkWithHeaders(...))

What I have now is a base Controller class that looks like

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

but that doesn't feel quite right. It feels like there should be more of an AOP-style way of defining the default headers and having them added to each response.

like image 360
Kenji Matsuoka Avatar asked Jul 13 '12 23:07

Kenji Matsuoka


2 Answers

The topic is quite old now, but with Play 2.1 it is even simpler now. Your Global.scala class should look like this :

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"
    ))
  }
}
like image 160
Bob G Avatar answered Oct 20 '22 01:10

Bob G


In your Global.scala, wrap every call in an action:

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)
    }
  }

}

In this case, I only call the action in dev mode, which makes most sense for a no-cache instruction.

like image 27
Marius Soutier Avatar answered Oct 20 '22 01:10

Marius Soutier