浏览器在更改 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 服务器和 backboneCORS 问题。这是我的 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 的提示:

了解和使用 CORS - https://templth.wordpress.com/2014/11/12/understanding-and-using-cors/

希望对你有帮助, 蒂埃里

【讨论】:

【参考方案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 请求中发送自定义标头?

CouchDB 中的 _users 数据库不允许使用 HTTP OPTIONS 方法

Azure 函数和 HTTP OPTIONS 请求