Search code examples
angularjsgoogle-app-enginecorsrestlet

Restlet + Google App Engine + CORS


I am using Restlet on Google App Engine for developing my sample application. The front end is Angular 2 App.

The Rest API is working fine with browser. However, I am getting the following issue when I am trying to hit the URL from Angular app.

XMLHttpRequest cannot load https://1-dot-jda-saas-training-02.appspot.com/rest/projectsBillingInfo/123. The 'Access-Control-Allow-Origin' header contains multiple values 'http://evil.com/, *', but only one is allowed. Origin 'http://localhost:3000' is therefore not allowed access.

So, I thought I will go ahead and add the CORS headers in the response. I used CorsFilter for that as follows but the issue is still there. When I see the header of the Response, I do not see any CORS headers. What am I missing here?

@Override
public Restlet createInboundRoot() {



    // Create a router Restlet that routes each call to a
    // new instance of HelloWorldResource.
    Router router = new Router(getContext());


    CorsFilter corsFilter = new CorsFilter(getContext(), router);
    corsFilter.setAllowedOrigins(new HashSet<String>(Arrays.asList("*")));
    corsFilter.setAllowedCredentials(true);
    // Defines only one route
    router.attachDefault(AddressServerResource.class);
    router.attach("/contact/123",ContactServerResource.class);
    router.attach("/projectsBillingInfo/123",ProjectBillingResource.class);
    return corsFilter;

}


EDIT

I could get this working. May be I was doing some mistake. But, I am not able to make this work with the GaeAuthenticator. When I am putting the GaeAuthenticator along with Corsfilter, it skips the authentication part of it. So, either the authentication works or the corsfilter works but not both. Is there any easy way to set/modify HTTP headers in restlet.

Here is the code I am using ..

   @Override
public Restlet createInboundRoot() {



    // Create a router Restlet that routes each call to a
    // new instance of HelloWorldResource.
    Router router = new Router(getContext());        

    // Defines only one route
    router.attachDefault(AddressServerResource.class);
    router.attach("/contact/123",ContactServerResource.class);
    router.attach("/projectsBillingInfo/123",ProjectBillingResource.class);

    GaeAuthenticator guard = new GaeAuthenticator(getContext());
    guard.setNext(router);



    CorsFilter corsFilter = new CorsFilter(getContext(), router);
    corsFilter.setAllowedOrigins(new HashSet<String>(Arrays.asList("*")));
    corsFilter.setAllowedCredentials(true);
    return corsFilter;

Solution

  • First, I think you can use the service instead of the filter:

    public MyApplication() {
        CorsService corsService = new CorsService();
        corsService.setAllowedCredentials(true);
        corsService.setSkippingResourceForCorsOptions(true);
        getServices().add(corsService);
    }
    

    Do you mind to set the "skippingServerResourceForOptions"?

    @Override
    public Restlet createInboundRoot() {
        // Create a router Restlet that routes each call to a
        // new instance of HelloWorldResource.
        Router router = new Router(getContext());
    
        // Defines only one route
    
        router.attachDefault(AddressServerResource.class);
        router.attach("/contact/123",ContactServerResource.class);
        router.attach("/projectsBillingInfo/123",ProjectBillingResource.class);
        return router;
    }
    

    Best regards, Thierry Boileau