Play 2.6 CORS configuration unexplained behaviour

466 views
Skip to first unread message

Bruno Batarelo

unread,
Jan 15, 2018, 8:45:41 PM1/15/18
to Play Framework
Hi all,

  I've been struggling with understanding why Play behaves in certain situations. First, let me give you context. There is a play framework server at localhost:9000 (nothing new here), and an angular 2 web app on localhost:4200 that makes a POST ajax call.

Problem is that I get: 
   "Failed to load http://localhost:9000/api/admin/login: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:4200' is therefore not allowed access. The response had HTTP status code 404."
when I don't expect it and I don't get it when I'd expect it.

According to Play documentation, following filters should be turned on automatically:

play.filters.csrf.CSRFFilter
play.filters.headers.SecurityHeadersFilter
play.filters.hosts.AllowedHostsFilter

and they are - I see that in console output when launching server.

Problem 1 - if I disable them, the message above is still present.
Having play.filters.enabled = [] in application.conf seems to disable filters because information about them in console output doesn't exist anymore. However, the above error is still present and I couldn't find explanation for that behaviour.

Additional observation
Both the server and the application come from the same domain - localhost. This should work regardless of CORS turned on or off, shouldn't it?

Problem 2 - if I install CORS by using Filters.scala, I effectively disable CORS and achieve what I believe should be done by disabling filters

Consider this class in project root:
class Filters @Inject() (corsFilter: CORSFilter) extends DefaultHttpFilters(corsFilter) {
}

I know that Filters.scala is prioritised over the rest of configuration, but this doesn't do anything. It doesn't override filters and yet, it disables CORS.

Another interesting thing is that if I do override filters and do something like override val filters = Seq(corsFilter), filter starts working, but in browser console I get status 500 whereas when filters are turned on by default (or turned off by play.filters.enabled = []) usual response is 403.


Problem 3 - I don't seem to be able to expose that famous Access-Control-Allow-Origin header. There was somebody here who claimed that things started working for him after making this configuration:

filters: {
enabled += "play.filters.cors.CORSFilter"
cors {
pathPrefixes = ["/"]
allowedOrigins = null
allowedHttpMethods = null
allowedHttpHeaders = null
exposedHeaders = ["Access-Control-Allow-Origin", "content-type"]
preflightMaxAge = 3 days
}
}

but only after he manually turned on filters with this line: enabled += "play.filters.cors.CORSFilter".
First, that doesn't make any sense because filters should already be on regardless of that line, and 2nd, the solution doesn't work for me.

I tested these scenarios on Play 2.6.9 and 2.6.11.

This topic isn't covered very much here and I don't understand why suddenly it became so hard to make an ajax call from the same host where server is running. I have a feeling that when I move single page web app somewhere else I'll just hit another can of worms.

Is there anyone here who successfully configured CORS in vanilla scenario that 99% of people have?

Many thanks,
Bruno

Christian Kaps

unread,
Jan 16, 2018, 2:30:30 AM1/16/18
to Play Framework
Hi,

do you have a node dev server running for your Angular app? Then you should add the ""Access-Control-Allow-Origin": "*"" header there. 

Here is a running example with CORS enabled. Maybe that helps.

Best regards,
Christian

Christian Kaps

unread,
Jan 16, 2018, 2:32:51 AM1/16/18
to Play Framework
Reply all
Reply to author
Forward
0 new messages