Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to enable Cross domain requests on JAX-RS web services?

I developed a set of restful web services. I couldn't call any of these methods from remote clients due to the error No 'Access-Control-Allow-Origin' header is present on the requested resource.

The services work perfectly on localhost. Is there any changes or configs to do on the server side to resolve the issue. i.e. to enable cross domain requests.

I'm using WildFly 8, JavaEE 7

like image 382
Naili Avatar asked May 03 '14 22:05

Naili


People also ask

How do you implement CORS in REST API?

To support CORS, therefore, a REST API resource needs to implement an OPTIONS method that can respond to the OPTIONS preflight request with at least the following response headers mandated by the Fetch standard: Access-Control-Allow-Methods. Access-Control-Allow-Headers. Access-Control-Allow-Origin.


2 Answers

I was wondering the same thing, so after a bit of research I found that the easiest way was simply to use a JAX-RS ContainerResponseFilter to add the relevant CORS headers. This way you don't need to replace the whole web services stack with CXF (Wildfly uses CXF is some form, but it doesn't look like it uses it for JAX-RS maybe only JAX-WS).

Regardless if you use this filter it will add the headers to every REST webservice.

package com.yourdomain.package;  import java.io.IOException;  import javax.ws.rs.container.ContainerRequestContext; import javax.ws.rs.container.ContainerResponseContext; import javax.ws.rs.container.ContainerResponseFilter; import javax.ws.rs.ext.Provider;  @Provider public class CORSFilter implements ContainerResponseFilter {     @Override    public void filter(final ContainerRequestContext requestContext,                       final ContainerResponseContext cres) throws IOException {       cres.getHeaders().add("Access-Control-Allow-Origin", "*");       cres.getHeaders().add("Access-Control-Allow-Headers", "origin, content-type, accept, authorization");       cres.getHeaders().add("Access-Control-Allow-Credentials", "true");       cres.getHeaders().add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD");       cres.getHeaders().add("Access-Control-Max-Age", "1209600");    }  } 

Then when I tested with curl, the response had the CORS headers:

$ curl -D - "http://localhost:8080/rest/test" HTTP/1.1 200 OK X-Powered-By: Undertow 1 Access-Control-Allow-Headers: origin, content-type, accept, authorization Server: Wildfly 8 Date: Tue, 13 May 2014 12:30:00 GMT Connection: keep-alive Access-Control-Allow-Origin: * Access-Control-Allow-Credentials: true Transfer-Encoding: chunked Content-Type: application/json Access-Control-Max-Age: 1209600 Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS, HEAD 

My understanding is that it's the @Provider annotation that tells the JAX-RS runtime to use the filter, without the annotation nothing happens.

I got the idea about using the ContainerResponseFilter from a Jersey example.

like image 78
Joel Pearson Avatar answered Sep 28 '22 01:09

Joel Pearson


I was facing a similar problem, and had tried to use @Alex Petty's solution, but apart from having to set the CORS headers on each JAX-RS endpoint in my class, as such:

@GET @Produces(MediaType.APPLICATION_JSON) public Response getMemberList() {     List<Member> memberList = memberDao.listMembers();     members.addAll(memberList);     return Response             .status(200)             .header("Access-Control-Allow-Origin", "*")             .header("Access-Control-Allow-Headers", "origin, content-type, accept, authorization")             .header("Access-Control-Allow-Credentials", "true")             .header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD")             .header("Access-Control-Max-Age", "1209600")             .entity(memberList)             .build(); } 

I had to further define a catch-all OPTIONS endpoint that would return the CORS headers for any other OPTIONS request in the class, and thus catch all endpoint of the sort:

@OPTIONS @Path("{path : .*}") public Response options() {     return Response.ok("")             .header("Access-Control-Allow-Origin", "*")             .header("Access-Control-Allow-Headers", "origin, content-type, accept, authorization")             .header("Access-Control-Allow-Credentials", "true")             .header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD")             .header("Access-Control-Max-Age", "1209600")             .build(); } 

Only after doing this, could I properly use my JAX-RS API endpoints from Jquery Ajax clients on other domains or hosts.

like image 44
JWL Avatar answered Sep 28 '22 03:09

JWL