Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ajax request with JAX-RS/RESTEasy implementing CORS

I have two servers (Apache and JBoss AS7) and I need to provide access to all http methods to a client. All these request must be sent via ajax. Example of the client code:

$.ajax({
      type: "get",
      url: "http://localhost:9080/myproject/services/mobile/list",
      crossDomain: true,
      cache: false,
      dataType: "json",
      success: function(response) {
        console.log(response);
      },
      error: function (jqXHR, textStatus, errorThrown) {
        console.log(textStatus);
        console.log(jqXHR.responseText);
        console.log(errorThrown);
        }
    });

In JBoss AS7 I'm using RESTEasy, implementing CORS as follows:

@Path("/mobile")
@Provider
@ServerInterceptor
public class GroupMobile implements MessageBodyWriterInterceptor {

@Inject
private GroupDAO groupDAO;

@GET
@Path("/list")
@Produces(MediaType.APPLICATION_JSON)
public List<Group> getGroups() {
    return groupDAO.listAll();
}

@Override
public void write(MessageBodyWriterContext context) throws IOException,
        WebApplicationException {
    context.getHeaders().add("Access-Control-Allow-Origin", "*");
    context.proceed();
}

@OPTIONS
@Path("/{path:.*}")
public Response handleCORSRequest(
        @HeaderParam("Access-Control-Request-Method") final String requestMethod,
        @HeaderParam("Access-Control-Request-Headers") final String requestHeaders) {
    final ResponseBuilder retValue = Response.ok();

    if (requestHeaders != null)
        retValue.header("Access-Control-Allow-Headers", requestHeaders);

    if (requestMethod != null)
        retValue.header("Access-Control-Allow-Methods", requestMethod);

    retValue.header("Access-Control-Allow-Origin", "*");

    return retValue.build();
}
}

web.xml and beans.xml are empty files. When I access MyIP:8080 (Apache), I get the error message:

XMLHttpRequest cannot load http://localhost:9080/myproject/services/mobile/list?_=1359480354190. Origin http://MyIP:8080 is not allowed by Access-Control-Allow-Origin.

Does anybody know what is wrong?

like image 328
Leo Avatar asked Jan 29 '13 17:01

Leo


3 Answers

The newest resteasy (3.0.9-Final) include a utility class org.jboss.resteasy.plugins.interceptors.CorsFilter.

You can add the CorsFilter object into Application's singleton objects set, or add it into ProviderFactory in ResteasyDeployment directly.

The following is the sample application class:

import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.ApplicationPath;

import org.jboss.resteasy.plugins.interceptors.CorsFilter;


@ApplicationPath("/api")
public class RestApplication extends javax.ws.rs.core.Application {
    Set<Object> singletons;

    @Override
    public Set<Class<?>> getClasses() {
        HashSet<Class<?>> clazzes = new HashSet<>();
        clazzes.add(VersionService.class);
        return clazzes;
    }

    @Override
    public Set<Object> getSingletons() {
        if (singletons == null) {
            CorsFilter corsFilter = new CorsFilter();
            corsFilter.getAllowedOrigins().add("*");

            singletons = new LinkedHashSet<Object>();
            singletons.add(corsFilter);
        }
        return singletons;
    }
}
like image 185
sca. Avatar answered Sep 17 '22 23:09

sca.


The problem you are having is your are trying to do cross-site scripting. You accessed the page at http://MyIP:8080 and so the browser is preventing you from accessing resources outside that domain. This is very browser specific and browser based work arounds will all be different (you can disable security in Chrome globally, and on a per site basis in IE).

If you load the page as http://localhost:8080, it should then allow you access the query. Alternatively, you can implement a proxy which will forward the request.

like image 32
Mark Robinson Avatar answered Sep 19 '22 23:09

Mark Robinson


Sounds like the issue is related to https://issues.jboss.org/browse/RESTEASY-878. You may not be able to catch CORS preflight requests with MessageBodyWriterInterceptor. Try using servlet filters (@WebFilter) instead.

like image 23
Tadayoshi Sato Avatar answered Sep 19 '22 23:09

Tadayoshi Sato