I recently needed to apply CORS (Cross Origin Request Scripting) to a project that I'm working on. If found 2 posts that helped to achieve it:
I combined both to solve my problem: I have a User CRUD (Play!) webservice and a (Play!) web app that services a SPA (Single Page Application). The SPA needs to access the CRUD webservice, but to acheive this, I would need to apply some CORS rules on both applications.
The build.sbt
shows that the filter
plugin is required.
libraryDependencies ++= Seq(
// Add here the specific dependencies for this module:
filters
)
In the CRUD application's Global.scala
file we've created a filter (CorsFilter
) which we apply to out Global construct
object Global extends WithFilters(CorsFilter) with GlobalSettings {
...
}
object CorsFilter extends Filter {
def apply (nextFilter: (RequestHeader) => Future[Result])(requestHeader: RequestHeader): Future[Result] = {
nextFilter(requestHeader).map { result =>
result.withHeaders(HeaderNames.ACCESS_CONTROL_ALLOW_ORIGIN -> "*",
HeaderNames.ALLOW -> "*",
HeaderNames.ACCESS_CONTROL_ALLOW_METHODS -> "POST, GET, PUT, DELETE, OPTIONS",
HeaderNames.ACCESS_CONTROL_ALLOW_HEADERS -> "Origin, X-Requested-With, Content-Type, Accept, Referer, User-Agent"
)
}
}
}
For the web app, we need to include routes for OPTIONS
that call on our CORS actions
...
OPTIONS / controllers.Application.options(path="")
OPTIONS /*path controllers.Application.options(path)
...
In our Application
file, we define a CORS action to apply the CORS headers
// Adds the CORS header
case class CorsAction[A](action: Action[A]) extends Action[A] {
def apply(request: Request[A]): Future[Result] = {
action(request).map(result => result.withHeaders(HeaderNames.ACCESS_CONTROL_ALLOW_ORIGIN -> "*",
HeaderNames.ALLOW -> "*",
HeaderNames.ACCESS_CONTROL_ALLOW_METHODS -> "POST, GET, PUT, DELETE, OPTIONS",
HeaderNames.ACCESS_CONTROL_ALLOW_HEADERS -> "Origin, X-Requested-With, Content-Type, Accept, Referer, User-Agent"
))
}
lazy val parser = action.parser
}
We then can implement the options
action as a CORSAction
that applies the CORS headers
object Application extends Controller {
...
def options(path: String) = CorsAction {
Action { request =>
Ok.withHeaders(ACCESS_CONTROL_ALLOW_HEADERS -> Seq(AUTHORIZATION, CONTENT_TYPE, "Target-URL").mkString(","))
}
}
}