/*set the response header*/
Form responseHeaders = (Form) getResponse().getAttributes().get("org.restlet.http.headers");
if (responseHeaders == null) {
responseHeaders = new Form();
responseHeaders.add("Access-Control-Allow-Origin", "*");
responseHeaders.add("Access-Control-Allow-Methods", "POST, GET, PUT, DELETE");
getResponse().getAttributes().put("org.restlet.http.headers", responseHeaders);
}
I added this in my restlet 2.0 code to allow for cross domain access, this does make the first GET to work on page load, but when I try to do POST later(with backbone model.save()), browser sends Options with a null entity instead.
It does send the right POST if I did not add the code above
This happens on Opera, Firefox, and Chrome (works fine if I start chrome with --disable-web-security), so i assume it is still a browser security issue, could anyone provide explanations on why this would happen and what might be the fix?
From What is the HTTP OPTIONS method?
This method allows the client to determine the options and/or requirements associated with a resource, or the capabilities of a server, without implying a resource action or initiating a resource retrieval.
I have fought several times with CORS issues and I have always solved them with the method of try and error my suggestion for your case is add OPTIONS
to your Allow Methods :
"Access-Control-Allow-Methods": "POST, GET, PUT, DELETE, OPTIONS"
And make your server to respond to OPTIONS
request with an *
, in Sinatra is like this:
options "/*" do
"*"
end
Update
For the new issue explained in the comment about the error header field Content-Type is not allowed by Access-Control-Allow-Headers.
Try to add another CORS header:
"Access-Control-Allow-Headers": "origin, x-requested-with, content-type"
Thanks for fguillen's advice, have some googling I found the way that would work
/*set the response header*/
Form responseHeaders = (Form) getResponse().getAttributes().get("org.restlet.http.headers");
if (responseHeaders == null) {
responseHeaders = new Form();
responseHeaders.add("Access-Control-Allow-Origin", "*");
responseHeaders.add("Access-Control-Allow-Methods", "POST, GET, PUT, DELETE, OPTIONS");
responseHeaders.add("Access-Control-Allow-Headers", "Content-Type");
getResponse().getAttributes().put("org.restlet.http.headers", responseHeaders);
}
so this is the right code to inject for cors in Restlet 2.0 do not miss responseHeaders.add("Access-Control-Allow-Headers", "Content-Type"); at least when you are dealing with backbone
Slightly off topic but I thought it might be useful for somebody and save time.
I was having CORS issues with uwsgi server and backbone. This is part of my uwsgi.ini file which seem to work for POSTing.
[uwsgi]
add-header = Access-Control-Allow-Origin: *
add-header = Access-Control-Allow-Headers: origin, x-requested-with, content-type
add-header = Access-Control-Allow-Methods: POST,GET,PUT,OPTIONS,DELETE
add-header = Content-Type: application/json; charset=UTF-8
add-header = Accept: application/json
As mentioned by fguillen server needs to reply '*' for OPTIONS request.
Below code can be used to resolve cross domain issue in Restlet 2.0
Form responseHeaders = (Form) getResponse().getAttributes().get("org.restlet.http.headers");
if (responseHeaders == null) {
responseHeaders = new Form();
getResponse().getAttributes().put("org.restlet.http.headers", responseHeaders);
}
responseHeaders.add("Access-Control-Allow-Origin", "*");
responseHeaders.add("Access-Control-Allow-Methods", "GET,DELETE,PUT,POST,OPTIONS");
responseHeaders.add("Access-Control-Allow-Headers", "Content-Type");
responseHeaders.add("Access-Control-Allow-Credentials", "false");
responseHeaders.add("Access-Control-Max-Age", "60");
Perhaps this link could give you some hints about how CORS works and its support in Restlet with the CorsFilter
:
- Understanding and using CORS - https://templth.wordpress.com/2014/11/12/understanding-and-using-cors/
Hope it helps you, Thierry
On a different content the code give below works for Restlet 2.1 upwards.
import org.restlet.engine.header.Header;
private static final String HEADERS_KEY = "org.restlet.http.headers";
@SuppressWarnings("unchecked")
static Series<Header> getMessageHeaders(Message message) {
ConcurrentMap<String, Object> attrs = message.getAttributes();
Series<Header> headers = (Series<Header>) attrs.get(HEADERS_KEY);
if (headers == null) {
headers = new Series<Header>(Header.class);
Series<Header> prev = (Series<Header>)
attrs.putIfAbsent(HEADERS_KEY, headers);
if (prev != null) { headers = prev; }
}
return headers;
}
//The JSON Query "GET"
@Get("json")
public Representation toJson()
{
getMessageHeaders(getResponse()).add("Access-Control-Allow-Origin", "*");
getMessageHeaders(getResponse()).add("Access-Control-Allow-Methods", "POST,GET,OPTIONS");
getMessageHeaders(getResponse()).add("Access-Control-Allow-Headers", "x-requested-with,Content-Type");
getMessageHeaders(getResponse()).add("Access-Control-Allow-Credentials", "true");
getMessageHeaders(getResponse()).add("Access-Control-Max-Age", "60");
return get();
}
来源:https://stackoverflow.com/questions/12069850/browsers-send-options-instead-of-post-after-changing-http-header