Play Framework 2.3 - CORS Headers

UPDATE New Play 2.5 Offers New CORS Filter

Since the new Java version 2.3 completed the transfer of the Response class to the Promise class, the following code no longer works.

public class CorsAction extends Action.Simple { public Result call(Context context) throws Throwable{ Response response = context.response(); response.setHeader("Access-Control-Allow-Origin", "*"); //Handle preflight requests if(context.request().method().equals("OPTIONS")) { response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE"); response.setHeader("Access-Control-Max-Age", "3600"); response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content- Type, Accept, Authorization, X-Auth-Token"); response.setHeader("Access-Control-Allow-Credentials", "true"); response.setHeader("Access-Control-Allow-Origin", "*"); return ok() } response.setHeader("Access-Control-Allow-Headers","X-Requested-With, Content-Type, X- Auth-Token"); return delegate.call(context); } } 

I am developing an application in Play (Java) 2.3, and I have looked and tried different methods to include CORS, including methods for adding / OPTIONS to the routes file, without success.

I would really appreciate how the new Response implementation will handle this type of interception, because it does not seem to have any effects in the headers when implemented in the new Promise class.

Thanks for the help!

+6
source share
5 answers

Solved this:

All API responses from the server must contain the header: "Access-Control-Allow-Origin", "*". We need to write a wrapper for all responses to actions.

In Global.java

 import java.net.URL; import play.*; import play.libs.F.Promise; import play.mvc.Action; import play.mvc.Http; import play.mvc.Result; public class Global extends GlobalSettings { // For CORS private class ActionWrapper extends Action.Simple { public ActionWrapper(Action<?> action) { this.delegate = action; } @Override public Promise<Result> call(Http.Context ctx) throws java.lang.Throwable { Promise<Result> result = this.delegate.call(ctx); Http.Response response = ctx.response(); response.setHeader("Access-Control-Allow-Origin", "*"); return result; } } @Override public Action<?> onRequest(Http.Request request, java.lang.reflect.Method actionMethod) { return new ActionWrapper(super.onRequest(request, actionMethod)); } } 

Server requests, such as POST, PUT, precede the request before the server before the main request. The response to these pre-flight requests should contain the following headers:

Access-Control-Allow-Origin, Allow, Access-Control-Allow-Methods, POST, GET, PUT, DELETE, OPTIONS, Access-Control-Allow-Headers, Origin , X-Requested-With, Content-Type, Accept, Referer, User-Agent "

In routes add:

 OPTIONS /*all controllers.Application.preflight(all) 

In the Coltroller app:

 package controllers; import play.mvc.*; public class Application extends Controller { public static Result preflight(String all) { response().setHeader("Access-Control-Allow-Origin", "*"); response().setHeader("Allow", "*"); response().setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, DELETE, OPTIONS"); response().setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Referer, User-Agent"); return ok(); } } 

PS: With this approach, I did not need to create a scala filter for this.

+8
source

It looks like you solved your problem, but just for clarity ...

You are pretty close ... I believe that you do not need to create your own Response object, you can just call the one that was passed using the method:

 public Result call() throws Throwable { response().setHeader("Access-Control-Allow-Origin", "*"); //Handle preflight requests if(request().method().equals("OPTIONS")) { response().setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE"); response().setHeader("Access-Control-Max-Age", "3600"); response().setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content- Type, Accept, Authorization, X-Auth-Token"); response().setHeader("Access-Control-Allow-Credentials", "true"); response().setHeader("Access-Control-Allow-Origin", "*"); return ok(); } else { return badRequest(); } } 

Hope this helps.

+2
source

Cross message from enable-cors-in-java-play-framework-2-2-x .

The solutions offered by @alexhanschke do not work when a request throws an exception (internal server error), since filters are not applied when this happens (see https://github.com/playframework/playframework/issues/2429 ). To solve this, you must wrap the scala class and return it as a result, as shown below in full. Note that this still requires a given options route and a controller to process the parameter request.

See here all https://gist.github.com/tinusn/38c4c110f7cd1e1ec63f .

 import static play.core.j.JavaResults.BadRequest; import static play.core.j.JavaResults.InternalServerError; import static play.core.j.JavaResults.NotFound; import java.util.ArrayList; import java.util.List; import play.GlobalSettings; import play.api.mvc.Results.Status; import play.libs.F.Promise; import play.libs.Scala; import play.mvc.Action; import play.mvc.Http; import play.mvc.Result; import scala.Tuple2; import scala.collection.Seq; public class Global extends GlobalSettings { private class ActionWrapper extends Action.Simple { public ActionWrapper(Action<?> action) { this.delegate = action; } @Override public Promise<Result> call(Http.Context ctx) throws java.lang.Throwable { Promise<Result> result = this.delegate.call(ctx); Http.Response response = ctx.response(); response.setHeader("Access-Control-Allow-Origin", "*"); return result; } } /* * Adds the required CORS header "Access-Control-Allow-Origin" to successfull requests */ @Override public Action<?> onRequest(Http.Request request, java.lang.reflect.Method actionMethod) { return new ActionWrapper(super.onRequest(request, actionMethod)); } private static class CORSResult implements Result { final private play.api.mvc.Result wrappedResult; public CORSResult(Status status) { List<Tuple2<String, String>> list = new ArrayList<Tuple2<String, String>>(); Tuple2<String, String> t = new Tuple2<String, String>("Access-Control-Allow-Origin","*"); list.add(t); Seq<Tuple2<String, String>> seq = Scala.toSeq(list); wrappedResult = status.withHeaders(seq); } public play.api.mvc.Result toScala() { return this.wrappedResult; } } /* * Adds the required CORS header "Access-Control-Allow-Origin" to bad requests */ @Override public Promise<Result> onBadRequest(Http.RequestHeader request, String error) { return Promise.<Result>pure(new CORSResult(BadRequest())); } /* * Adds the required CORS header "Access-Control-Allow-Origin" to requests that causes an exception */ @Override public Promise<Result> onError(Http.RequestHeader request, Throwable t) { return Promise.<Result>pure(new CORSResult(InternalServerError())); } /* * Adds the required CORS header "Access-Control-Allow-Origin" when a route was not found */ @Override public Promise<Result> onHandlerNotFound(Http.RequestHeader request) { return Promise.<Result>pure(new CORSResult(NotFound())); } } 
+1
source

It worked for me. However, you may need to configure some settings (application.conf)

Step 1 Create a Filter Class (UrlFilter)

 package filters; import play.mvc.EssentialFilter; import play.filters.cors.CORSFilter; import play.http.DefaultHttpFilters; import javax.inject.Inject; public class UrlFilter extends DefaultHttpFilters { @Inject public UrlFilter(CORSFilter corsFilter) { super(corsFilter); } } 

Step 2 import filter package in build.sbt

 libraryDependencies += filters 

Step 3 Register the UrlFilter class in application.conf

 play.http.filters = "filters.UrlFilter" 

NOTE. Be sure to include the exact location. Mine was in the application /filters/UrlFilter.java

Step 4 Add actual configurations that allow "access control to allow origin" and more. To application.conf

  play.filters.cors { # The path prefixes to filter. pathPrefixes = ["/"] # 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 # The exposed headers exposedHeaders = [] # Whether to support credentials supportsCredentials = true # The maximum amount of time the CORS meta data should be cached by the client preflightMaxAge = 1 hour } 

Credit https://www.playframework.com/documentation/2.5.x/CorsFilter

https://www.playframework.com/documentation/2.5.x/resources/confs/filters-helpers/reference.conf

0
source

for me the configuration working in chrome, firefox and explorer:

Play Framework CORS Headers

0
source

Source: https://habr.com/ru/post/973395/


All Articles