Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Play Framework CORS Headers

I'm trying to set CORS Headers for my play framework app. Specifically I'm getting this error

cannot load http://127.0.0.1:9000/. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:9000' is therefore not allowed access.

I figured I could easily handle this by following these instructions: https://www.playframework.com/documentation/2.5.x/CorsFilter

However, after doing this. nothing has changed.

curl -I localhost:9000/
HTTP/1.1 200 OK
Content-Length: 4540
Content-Type: text/html; charset=utf-8
Date: Mon, 11 Jul 2016 20:03:33 GMT

My conf is:

play.http.filters = "global.Filters"

play.filters.cors {
  allowedOrigins = ["http://www.example.com", "*"]
  allowedHttpMethods = ["GET", "POST"]
  allowedHttpHeaders = ["Accept"]
}

and my Filters.scala file is:

package global

import javax.inject.Inject
import play.api.http.DefaultHttpFilters
import play.filters.cors.CORSFilter

class Filters @Inject() (corsFilter: CORSFilter)
  extends DefaultHttpFilters(corsFilter)

If someone could tell me why the filters don't seem to be getting applied to the responses, that'd be great.

like image 879
Aric Hunter Avatar asked Jul 11 '16 20:07

Aric Hunter


People also ask

What do CORS headers do?

Cross-Origin Resource Sharing (CORS) is an HTTP-header based mechanism that allows a server to indicate any origins (domain, scheme, or port) other than its own from which a browser should permit loading resources.

What is CORS filter?

CORS Filter is a generic solution for fitting Cross-Origin Resource Sharing (CORS) support to Java web applications. CORS is a W3C standard for enabling cross-domain requests from web browsers to servers and web APIs that opt in to handle them.


2 Answers

I would not recommend writing/using any code to enable CORS which is basically a framework feature and only needs configuration.

The stuff you copied from the documentation is correct:

  • cors.conf where you modify the play.filters.cors settings. But you seem to have misconfigured something, e.g. the allowedOrigin = * should be configured as null in the config. (Have a look at the documentation page and the linked reference.conf)

# The allowed origins. If null, all origins are allowed. play.filters.cors.allowedOrigins = null

  • You have correctly enabled the CORSFilter in your Filters.scala
  • Now test your configuration with a correct cURL CORS request:

curl -H "Origin: http://example.com" \ -H "Access-Control-Request-Method: GET" \ -H "Access-Control-Request-Headers: X-Requested-With" \ -X OPTIONS --verbose \ http://localhost:9000/

like image 24
mana Avatar answered Sep 22 '22 17:09

mana


Play filters are enticing, but when they do not work as expected, as you noticed, the magic is not that easy to track down.

I prefer to use something like this:

implicit class RichResult (result: Result) {
  def enableCors =  result.withHeaders(
    "Access-Control-Allow-Origin" -> "*"
    , "Access-Control-Allow-Methods" -> "OPTIONS, GET, POST, PUT, DELETE, HEAD"   // OPTIONS for pre-flight
    , "Access-Control-Allow-Headers" -> "Accept, Content-Type, Origin, X-Json, X-Prototype-Version, X-Requested-With" //, "X-My-NonStd-Option"
    , "Access-Control-Allow-Credentials" -> "true"
  )
}

Then you can easily invoke it in your response like this:

Ok(Json.obj("ok" -> "1")).enableCors

It's easy to understand, can be placed only where you want to enable CORS, and very easy to debug!

like image 50
B Faust Avatar answered Sep 25 '22 17:09

B Faust