浏览器在更改 http 标头后发送 Options 而不是 Post
Posted
技术标签:
【中文标题】浏览器在更改 http 标头后发送 Options 而不是 Post【英文标题】:browsers send Options instead of Post after changing http header 【发布时间】:2012-08-17 16:24:03 【问题描述】:/*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);
我在我的 restlet 2.0 代码中添加了这个以允许跨域访问,这确实使第一个 GET 在页面加载时工作,但是当我稍后尝试执行 POST 时(使用主干 model.save()),浏览器发送而是使用空实体的选项。
如果我没有添加上面的代码,它确实会发送正确的 POST
这发生在 Opera、Firefox 和 Chrome 上(如果我使用 --disable-web-security 启动 chrome 可以正常工作),所以我认为这仍然是浏览器安全问题,谁能解释为什么会发生这种情况?有什么解决办法?
【问题讨论】:
【参考方案1】:来自What is the HTTP OPTIONS method?
此方法允许客户端确定与资源相关的选项和/或要求,或服务器的功能,而无需暗示资源操作或启动资源检索。
我曾多次与 CORS 问题作斗争,我总是用 try and error 的方法解决它们,我对您的情况的建议是将 OPTIONS
添加到您的允许方法:
"Access-Control-Allow-Methods": "POST, GET, PUT, DELETE, OPTIONS"
并让您的服务器使用*
响应OPTIONS
请求,在Sinatra 中是这样的:
options "/*" do
"*"
end
更新
关于错误header field Content-Type is not allowed by Access-Control-Allow-Headers.
的评论中解释的新问题
尝试添加另一个 CORS 标头:
"Access-Control-Allow-Headers": "origin, x-requested-with, content-type"
【讨论】:
在我添加选项标头并返回 json 表示后,我得到:Access-Control-Allow-Headers 不允许请求标头字段 Content-Type。我真的不了解 Sinatra,有什么建议可以在 Restlet 中做到这一点吗?【参考方案2】:感谢 fguillen 的建议,用谷歌搜索我找到了可行的方法
/*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);
所以这是在 Restlet 2.0 中为 cors 注入的正确代码 不要错过 responseHeaders.add("Access-Control-Allow-Headers", "Content-Type");至少在您处理骨干时
【讨论】:
【参考方案3】:有点偏离主题,但我认为它可能对某人有用并节省时间。 我遇到了 uwsgi 服务器和 backbone 的 CORS 问题。这是我的 uwsgi.ini 文件的一部分,它似乎适用于 POST。
[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
如 fguillen 所述,服务器需要回复 '*' 以获取 OPTIONS 请求。
【讨论】:
【参考方案4】:以下代码可用于解决 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】:也许此链接可以为您提供一些关于 CORS 工作原理及其在 Restlet 中的支持CorsFilter
的提示:
希望对你有帮助, 蒂埃里
【讨论】:
【参考方案6】:在不同的内容上,下面给出的代码适用于 Restlet 2.1 以上。
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();
【讨论】:
以上是关于浏览器在更改 http 标头后发送 Options 而不是 Post的主要内容,如果未能解决你的问题,请参考以下文章
Angular $http 未在 OPTIONS 飞行前发送标头
在 .NET Core Web API 上为 CORS 启用 OPTIONS 标头
更改 ajax 请求的 response.statuscode 会引发错误“发送 HTTP 标头后服务器无法设置状态”
如何在 CORS 预检 OPTIONS 请求中发送自定义标头?