Call Play 2 REST API with AngularJS (CORS Problems

2019-08-02 19:41发布

I am developing an AngularJS application calling a REST API developed with Play Framework 2.2.0.

I have a problem related to Cross-domain ajax calls as the Angular application and the Play one will not be hosted on the same domain.

Here is the JS call in my Angular service :

    $http
        .post("http://localhost:9001/category/list", { langCode: 'fr-FR' })
        .success(function(data, status, headers, config) {
            callback(data.items);
        })
        .error(function(data, status, headers, config) {
            console.log("Error Data : " + data);
            console.log("Error Status : " + status);
        });

Here is the route in my Play app :

POST /category/list controllers.catalog.ProductCategoryController.list()

  • If I don't send any data in the request, everything works fine
  • If I send data, I have Ajax errors concerning ACCESS_CONTROL_ALLOW_ORIGIN, ACCESS_CONTROL_ALLOW_HEADERS

The only workaround I have is the following :

  • Intercept all requests in Global class and add the headers

    @Override public Action onRequest(Request request, Method method) { return new Action.Simple() { @Override public Promise<SimpleResult> call(Context ctx) throws Throwable { Logger.debug("Intercepting request and applying CORS headers..."); ctx.response().setHeader(Controller.ACCESS_CONTROL_ALLOW_ORIGIN, "*"); ctx.response().setHeader(Controller.ACCESS_CONTROL_ALLOW_HEADERS, "Content-Type"); return delegate.call(ctx); } }; }

  • Add another route with OPTIONS in routes

OPTIONS /category/list controllers.catalog.ProductCategoryController.list()

Is there a way of making the integration simpler than that ?

2条回答
太酷不给撩
2楼-- · 2019-08-02 19:45

You have to enable CORS support to your Play web server. The following url do have plenty of how-to for configurating server enabling the cross origin support:

http://enable-cors.org/server.html

查看更多
倾城 Initia
3楼-- · 2019-08-02 20:03

There's no CORS support out of the box in play; that's a situation I'd like to see changed, but for now you've identified a wart.

The good news is that you can manage a global workaround if you are OK having one CORS setting for all of your resources. It can be done in a couple of ways, one of which you identified. My inclination would be to go with a low level OPTIONS route.

Something like:

OPTIONS        /*path                         controllers.Application.options()

From there, your handler definition can be something like:

Ok("").withHeaders(
      "ACCESS_CONTROL_ALLOW_METHODS" -> "GET, POST, PUT, PATCH",
      "ACCESS_CONTROL_ALLOW_HEADERS"->"Content-Type", 
      "ACCESS_CONTROL_ALLOW_ORIGIN" -> "*"
)

It's not super clean, but until Play adds something a bit more workable, I think it's your best option over making tons of OPTIONS routes (again, assuming you're comfortable with a global CORS setting)

查看更多
登录 后发表回答