Trouble-shooting CORS in Play Framework 2.4.x
Asked Answered
D

7

9

I have a java play framework 2.4.x web app providing a JSON/HTTP API. When I run my front-end HTML/JS file:///Users/nize/tmp/index.html calling the API on http://localhost:9000 chrome shows

XMLHttpRequest cannot load http://localhost:9000. 
No 'Access-Control-Allow-Origin' header is present 
on the requested resource. Origin 'null' is therefore 
not allowed access. The response had HTTP status code 403.

I have configured the web app as per the instructions given in Play Framework 2.4.x CORS Documentation:

  • Update to build.sbt
  • Added the class Filters.javato the root of the project (also tried /app)
  • Added the following stanza to the application.conf:
    play.filters.cors {
      allowedOrigins = ["*","http://localhost"]
      #allowedHttpMethods = ["GET", "POST"]
      #allowedHttpHeaders = ["Accept"]
      #preflightMaxAge = 3 days
    }
    

What am I missing?

Edit: The symptoms look identical or similar to Other very similar stackoverflow post. That problem was solved by reconfiguring Cisco AnyConnect VPN which was installed on the computer. I, however, don't have that software installed.

Dread answered 12/8, 2015 at 21:8 Comment(2)
Your question helped me even before I looked at the answers below. I had implemented only the last part of the instructions in the documentation (Configuring the CORS filter in application.conf), missing the first two (updating build.sbt and adding Filters.java). So I battled with play until I stumbled upon your question which summarizes the steps I missed from the official documentation, and Radium's answer below which links to reference.conf. By the way, I was using Firefox, and also tested successfully with Chrome so this is not a Chrome-specific issue for me, and shouldn't even be.Cuprum
@Dread were you able to solve this? I have exact same issue. I also defined a controller method to handle OPTIONS requests but to no avail. I always get 403 using Ajax as well as PostmanHypaethral
C
15

First add/edit these lines(configurations) into your conf/application.conf

 play.filters.cors {
  # allow all paths
  pathPrefixes = ["/"]
  # allow all origins (You can specify if you want)
  allowedOrigins = null
  allowedHttpMethods = ["GET", "POST", "PUT", "DELETE"]
  # allow all headers
  allowedHttpHeaders = null
 }   

(Note that lines starting with '#' are commented lines.)

Then go to build.sbt and add this line.

libraryDependencies += filters

Finally make a Java Class named 'Filters.java' and include this to the root directory(/app).

import play.api.mvc.EssentialFilter;
import play.filters.cors.CORSFilter;
import play.http.HttpFilters;

import javax.inject.Inject;

public class Filters implements HttpFilters {

    @Inject
    CORSFilter corsFilter;

    public EssentialFilter[] filters() {
        return new EssentialFilter[] { corsFilter };
    }
}

You can refer official documentation for more information.

Chemo answered 18/5, 2016 at 4:53 Comment(4)
Worked perfectly for me, thanks. Note that the default app.conf file already had cors config - it is just a case of uncommenting / editing the relevant settings.Wolff
Type mismatch: cannot convert from CORSFilter to EssentialFilterDallas
@Dallas what is the play version you are using?Chemo
it is ok with corsFilter.asJava() version 2.5 thanksDallas
S
8

I had the same problem while following the same documentation.

Problem is with this CORS filter that you have used:

allowedOrigins = ["*","http://localhost"]

If you want to allow all origins use:

allowedOrigins = null

Follow the same for allowedHttpMethods

This is as per the documentation

To quote:

The allowed origins. If null, all origins are allowed.

allowedOrigins = null

Hope this helps!

Screwy answered 10/9, 2015 at 5:56 Comment(0)
H
5

I think the CORS filter in Play does not work! I followed step by step as but somehow I always got HTTP-403 in the browser (Chrome and Firefox) in Ajax calls. Problem is I don't even get stacktrace on server side. I think DefaultHttpErrorHandler in the CORS filter somehow gulp that. In the response "Access-Control-Allow-Origin" header was missing so I just manually added that.

class Filters @Inject() (corsFilter: CORSFilter, log: LoggingFilter) extends HttpFilters {
  def filters = {
    // CORS filter does not work
    //Seq(corsFilter, log)
    Seq(log)
  }
}

This is the logging filter (Credit: Play! framework)

class LoggingFilter extends Filter {

  def apply(nextFilter: RequestHeader => Future[Result])(requestHeader: RequestHeader): Future[Result] = {

    val startTime = System.currentTimeMillis

    nextFilter(requestHeader).map { result =>

      val endTime = System.currentTimeMillis
      val requestTime = endTime - startTime

      Logger.info(s"${requestHeader.method} ${requestHeader.uri} " +
        s"took ${requestTime}ms and returned ${result.header.status}")

      result.withHeaders(
        "Request-Time" -> requestTime.toString,
        "Access-Control-Allow-Origin" -> "*"   // Added this header
      )
    }
  }
}
Hypaethral answered 7/3, 2016 at 4:26 Comment(0)
T
1

I was experiencing a similar issue, I was getting 403's on requests. I solved a the problem by removing the:

allowedHttpHeaders=["Accept"] 

that they use in their example configuration. I'm still not clear what the security implications of that are, however, so YMMV.

Trainload answered 21/2, 2016 at 18:57 Comment(1)
this worked for me also. I'm also not sure what the security implications of this are.Inconsecutive
L
0

Does it work in Firefox? Chrome has some restrictions on running Ajax from local files, e.g., see this link. If it is Chrome-specific, you can start up Chrome with a command-line switch to remove the restriction.

Lavin answered 17/8, 2015 at 23:50 Comment(2)
Good point. I tried with firefox (MacOS) also, but I got 403 (forbidden).Dread
for me configuration working in chrome, firefox and explorer : #38316001Dallas
R
0

This will probably not solve the problem for the poster, but it solved the problem for me when I had the same symptoms, and I am posting it in case it can help others in the same situation.

I had actually misunderstood how CORS is working. I have two separate Play applications, one with a REST API and one with a web interface using the REST API. I followed the instructions in the documentation page mentioned in the question, but my mistake was that I did it on the web interface application. When I instead did it on the REST API application, it worked immediately.

Roadrunner answered 8/2, 2016 at 13:39 Comment(0)
I
0
filters = "filters.Filters"


play.filters {

  cors {

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

    # The allowed HTTP methods. If null, all methods are allowed
    allowedHttpMethods = null

    # The allowed HTTP headers. If null, all  headers are allowed.
    allowedHttpHeaders = null
  }

}



public class Filters implements HttpFilters {

    @Inject
    private CORSFilter corsFilter;

    public EssentialFilter[] filters() {
        return new EssentialFilter[] {
            corsFilter.asJava()
        };
    }

}
Indehiscent answered 30/4, 2016 at 20:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.