OPTIONS request for restful cross-domain using COR

2020-02-14 04:55发布

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.

4条回答
该账号已被封号
2楼-- · 2020-02-14 05:00

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 :)

查看更多
太酷不给撩
3楼-- · 2020-02-14 05:05

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>
查看更多
Fickle 薄情
4楼-- · 2020-02-14 05:21

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:

  1. Applies the CORS header you need to the response.
  2. Returns the HTTP status code 200 when calling an endpoint with the OPTIONS method. You tell the client that its CORS preflight requests were accepted.

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.

查看更多
女痞
5楼-- · 2020-02-14 05:22

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>
查看更多
登录 后发表回答