Reputation: 41
On client side I'm using Ajax.post (jquery 1.5) with json. On server side I'm using rest resteasy-jaxrs-2.0.1.GA. I found somewhere that i should add couple of headers to server response and I've done with following filter:
public void doFilter( ServletRequest req,
ServletResponse res,
FilterChain filterChain)
throws IOException, ServletException {
MyServletRequestWrapper httpReq = new MyServletRequestWrapper((HttpServletRequest)req);
HttpServletResponse httpRes = (HttpServletResponse)res;
HttpSession session = httpReq.getSession();
httpRes.addHeader(ACCESS_CONTROL_ALLOW_ORIGIN, "*");
httpRes.addHeader(ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");
if (((HttpServletRequest) req).getMethod().equals("OPTIONS")){
httpRes.addHeader(ACCESS_CONTROL_ALLOW_METHODS, "GET, POST, OPTIONS, PUT, DELETE");
httpRes.addHeader(ACCESS_CONTROL_ALLOW_HEADERS, "content-type, x-requested-with, x-requested-by");
}
filterChain.doFilter(httpReq, httpRes);
}
It works fine cause to every single GET response above headers are added. Problem appears when I want to use POST request. When I use Ajax.post, at first server gets OPTIONS request and I've got following error:
Failed executing OPTIONS [REST_PATH]
org.jboss.resteasy.spi.DefaultOptionsMethodException: No resource method found for options, return OK with Allow header
To solve above error I was trying to add method invoke with the same path as POST ([REST_PATH]) but with @OPTION annotation. In that case javac told me that symbol :class OPTIONS could not be found, even there is a OPTION.class in attached jaxrs library.
Any ideas to fix it? I would be very grateful for any clues.
Upvotes: 4
Views: 8361
Reputation: 3492
When I was trying to call my service with an Angular 2 client RestEasy was responding to the preflight requests with the HTTP status 500 and the following error.
RESTEASY003655: No resource method found for options, return OK with Allow header
I tried RestEasy's CorsFilter but I'd like to propose a simple alternative. What if you don't want to write code handling the OPTIONS call for each of your endpoints ?
I implemented a simple filter that:
Here is the code. Feel free to refine the filter if you only want to send back a 200 when querying a "real" endpoint.
@Provider
public class CorsFilter implements ContainerResponseFilter {
@Override
public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
MultivaluedMap<String, Object> headers = responseContext.getHeaders();
headers.add("Access-Control-Allow-Origin", "*"); // If you want to be more restrictive it could be localhost:4200
headers.add("Access-Control-Allow-Methods", "GET, PUT, POST, OPTIONS"); // You can add HEAD, DELETE, TRACE, PATCH
headers.add("Access-Control-Allow-Headers", "Content-Type, Authorization, Accept, Accept-Language"); // You can add many more
if (requestContext.getMethod().equals("OPTIONS"))
responseContext.setStatus(200);
}}
Make sure to understand CORS too.
Upvotes: 1
Reputation: 6372
There is a built in CORS filter in tomcat. http://tomcat.apache.org/tomcat-7.0-doc/config/filter.html
<filter>
<filter-name>CorsFilter</filter-name>
<filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CorsFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Upvotes: 0
Reputation: 11
The CORS filter may be fine. I would like to point out as you wrote "To solve above error I was trying to add method invoke with the same path as POST ([REST_PATH]) but with @OPTION annotation. In that case javac told me that symbol :class OPTIONS could not be found, " that you had a typo there instead of @OPTIONS
you wrote @OPTION
without the S
:)
Upvotes: 0
Reputation: 2727
This question is quite old, but as a reference for others with similar problems - just recently i came across a nice "CORS Filter" you may want to consider using. It's just a matter of adding the following lines to your web.xml and it works like a charm.
<filter>
<filter-name>CORS</filter-name>
<filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CORS</filter-name>
<servlet-name>MyServletNameGoesHere</servlet-name>
</filter-mapping>
and the maven dependency:
<dependency>
<groupId>com.thetransactioncompany</groupId>
<artifactId>cors-filter</artifactId>
<version>1.5.1</version>
</dependency>
Upvotes: 1