I am working on a project which is using embedded Jetty (unfortunately I just "inherited" the server side of the project and am not very familiar with the use of Jetty and its configuration).
An odd case just popped up - I'll do my best to describe:
A web-based UI (using AngularJS, from a different domain, so CORS is used) sends a POST request to change the state of something on the server. This worked at some point in the past (it was last used probably a month or so ago).
Yesterday this stopped working. Inspecting the REST calls, I saw that an OPTIONS request is first being made. The content type of the POST is application/json, so based on what I have read, this is correct. I am not sure why it was previously not sent - it is possible that the company had its version of Chrome updated recently, and the old version did not send preflight requests, but that's just speculation. In any case, here's what I think is the relevant code in my application for configuring Jetty for CORS:
FilterHolder holder = new FilterHolder(new CrossOriginFilter());
holder.setInitParameter(CrossOriginFilter.ALLOWED_ORIGINS_PARAM, "*");
holder.setInitParameter(CrossOriginFilter.ACCESS_CONTROL_ALLOW_CREDENTIALS_HEADER, "true");
appHandler.addFilter(holder, "/*", EnumSet.of(DispatcherType.REQUEST));
Everything works fine for POST requests. I can verify this by starting Chrome with the --disable-web-security flag. No OPTIONS request is sent, and the POST works as it should.
My thinking is that since it works for the POST, it's not an authorization or security issue - it's just that Jetty is not configured properly to handle the preflight request (it just returns 401).
I can't find much documentation for embedded Jetty, and which of the CrossOriginFilter constants to use as property keys in the calls to setInitParameter (and furthermore, since the 2nd argument to that method call is a String, I really have no idea how to format the values).
What parameters should I be setting on CrossOriginFilter to property handle OPTIONS requests? And if I have said anything erroneous above or made any false assumptions, please correct me! I've got very limited experience with this.
Documentation for CrossOriginFilter:
http://www.eclipse.org/jetty/documentation/current/cross-origin-filter.html
Javadoc for CrossOriginFilter:
http://download.eclipse.org/jetty/stable-9/apidocs/org/eclipse/jetty/servlets/CrossOriginFilter.html
Actual Source Code: (sometimes this helps people understand too):
In short, you'll likely want to add OPTIONS to the allowed methods.
(Just like the javadoc says)
FilterHolder holder = new FilterHolder(new CrossOriginFilter());
holder.setInitParameter(CrossOriginFilter.ALLOWED_METHODS_PARAM, "GET,POST,HEAD,OPTIONS");
appHandler.addFilter(holder, "/*", EnumSet.of(DispatcherType.REQUEST));
Now, to address another bug you have ...
This does nothing ...
holder.setInitParameter(CrossOriginFilter.ACCESS_CONTROL_ALLOW_CREDENTIALS_HEADER,
"true");
That is not an init parameter key. (In fact that is a header name constant for the Access-Control-Allow-Credentials
) if you want to allow credentials, then do as the javadoc says.
holder.setInitParameter(CrossOriginFilter.ALLOW_CREDENTIALS_PARAM, "true");