Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Implement CORS Request Headers in PlayFramework 2.3.x Applications

Introduction

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.

Files

CRUD WebService

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

Web App

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(","))
		}
	}
}
# Application Routes
# This file defines application routes (Higher priority routes first)
# ~~~~
GET ...
OPTIONS / controllers.Application.options(path="")
OPTIONS /*path controllers.Application.options(path)
package controllers
import play.Play
import play.api.http.HeaderNames
import play.api.mvc._
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
object Application extends Controller {
...
def options(path: String) = CorsAction {
Action { request =>
Ok.withHeaders(ACCESS_CONTROL_ALLOW_HEADERS -> Seq(AUTHORIZATION, CONTENT_TYPE, "Target-URL").mkString(","))
}
}
}
// 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
}
name := "cors-play"
organization := "com.example"
version := "0.1-SNAPSHOT"
scalaVersion := "2.11.1"
lazy val root = (project in file(".")).enablePlugins(PlayScala)
libraryDependencies ++= Seq(
// Add here the specific dependencies for this module:
filters
)
resolvers ++= Common.commonResolvers
import play.api._
import play.api.http.HeaderNames
import play.api.mvc._
import play.api.mvc.Results._
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
object Global extends WithFilters(CorsFilter) with GlobalSettings {
// called when a route is found, but it was not possible to bind the request parameters
override def onBadRequest (request: RequestHeader, error: String) = Future.successful(
BadRequest("Bad Request: " + error)
)
}
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"
)
}
}
}
@nishanpatel

This comment has been minimized.

Copy link

commented Sep 27, 2015

Hi Mitchell,

Thanks for sharing such a nice article.

I have implemented CORS as you mentioned here in your article. Currently I am working on play framework and angular application and facing “No 'Access-Control-Allow-Origin' header is present on the requested resource” issue. I have mentioned my problem on below URL,

http://stackoverflow.com/questions/32808368/redirect-issue-from-localhost-using-play-framework-angularjs

Can you please help me to resolve the same?

@arpitkulria

This comment has been minimized.

Copy link

commented Jul 1, 2016

@nishanpatel: -
By looking above example, You have to add "access-control-allow-origin" in HeaderNames.ACCESS_CONTROL_ALLOW_HEADERS in Global.scala file.

@ankushbindra

This comment has been minimized.

Copy link

commented Jul 26, 2016

it really helps thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.