问题
/*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?
回答1:
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"
回答2:
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
回答3:
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.
回答4:
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");
回答5:
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
回答6:
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