restlet / restlet-framework-java

The first REST API framework for Java
https://restlet.talend.com
Other
654 stars 284 forks source link

CORS implementation broken after upgrading to version 2.3.2 #1088

Open twilek opened 9 years ago

twilek commented 9 years ago

I have my own implementation of core, where I use the Access-Control-*-headers as custom headers. But after upgrading to 2.3.2 this implementation all of the sudden stopped working and the log was telling me "ddition of the standard header "Access-Control-Allow-Origin" is not allowed. Please use the equivalent property in the Restlet API."

After that I noticed that the CORS headers now have their own setters on the response object. So I changed my implementation to use them instead. The problem though is that some headers still is not present so I still have to use custom headers ("Access-Control-Max-Age" for example).

So my main concerns here are 1.) that the changes done between 2.3.1 and 2.3.2 was not backward compatible which resulted in errors in runtime 2.) that it will break again in runtime when you add new headers to your standard headers 3.) that some headers still is not presented so 1. and 2. will happen again in future version of the code as long as you do not allow standard headers to be added also as custom headers.

zhouning commented 9 years ago
            CorsService cors=new CorsService();
    cors.setAllowedOrigins(new HashSet(Arrays.asList("*")));
    cors.setAllowedCredentials(true);

    Application test=new Application();
    test.getServices().add(cors);

    this.getDefaultHost().attachDefault(test);
thboileau commented 9 years ago

Actually, the initial intention was to use the set of headers only for the "non standard" ones. A bug has been introduced at some time, and "fixed" in release 2.3.2. But we understand your point of view. Let's keep this issue open.

fellahst commented 9 years ago

Is this bug fixed ? I run into similar problem, when I initialize my application with the following code

CorsService corsService = new CorsService();
corsService.setAllowingAllRequestedHeaders(true);
corsService.setAllowedOrigins( new HashSet(Arrays.asList("*")));
corsService.setAllowedCredentials(true);

getServices().add( corsService );      

I tested with version 2.3.0, 2.3.2, 2.3.4. What do I miss ?

thboileau commented 9 years ago

Hi @fellahst ,

I've tried your code and it runs well for me using the 2.3.4 version. What kind of issues do you get?

Here is my sample test code. All files are located in a "cors" package.

package cors;

import java.util.Arrays;
import java.util.HashSet;

import org.restlet.Application;
import org.restlet.Component;
import org.restlet.Restlet;
import org.restlet.data.Protocol;
import org.restlet.resource.Directory;
import org.restlet.routing.Router;
import org.restlet.service.CorsService;

public class TestCorsApplication extends Application {

    public static void main(String[] args) throws Exception {
        Component c = new Component();
        c.getServers().add(Protocol.HTTP, 8182);
        c.getClients().add(Protocol.CLAP);
        c.getDefaultHost().attach(new TestCorsApplication());

        c.start();
    }

    public TestCorsApplication() {
        CorsService corsService = new CorsService();
        corsService.setAllowingAllRequestedHeaders(true);
        corsService.setAllowedOrigins(new HashSet(Arrays.asList("*")));
        corsService.setAllowedCredentials(true);

        getServices().add(corsService);
    }

    @Override
    public Restlet createInboundRoot() {
        Router router = new Router(getContext());
        router.attach("/hello", HelloResource.class);
        router.attachDefault(new Directory(getContext(), "clap://class/cors/"));
        return router;
    }

}
package cors;

import org.restlet.resource.Get;
import org.restlet.resource.ServerResource;

public class HelloResource extends ServerResource {

    @Get("txt")
    public String hello() {
        return "hello, world";
    }

}
<html><head>
<script>
function myFunction() {
    var xhr = new XMLHttpRequest();
    xhr.open('GET', 'http://tboi.com:8182/hello', true);
    xhr.setRequestHeader('X-test', 'test');
    xhr.onreadystatechange = function () {
      if (this.status == 200 && this.readyState == 4) {
        alert('response: ' + this.responseText);
      }
    };
    xhr.send();
}
</script>
</head>
<body>
<button onclick="myFunction();">Click me</button>
</body>
</html>

In a browser, I go to resource: http://localhost:8182/index.html, it shows a page with a single button. When clicking on it, it must display a popup window with hello, world message.

thboileau commented 8 years ago

Hello @fellahst , had you some time to test this feature?