我正在构建一个web API。我发现每当我使用Chrome POST, GET到我的API,总是有一个选项请求发送之前的真正的请求,这是相当恼人的。目前,我让服务器忽略任何OPTIONS请求。现在我的问题是,发送一个OPTIONS请求来增加服务器的负载有什么好处呢?有没有办法完全停止浏览器发送OPTIONS请求?
当前回答
我已经解决了这个问题。
if($_SERVER['REQUEST_METHOD'] == 'OPTIONS' && ENV == 'devel') {
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Headers: X-Requested-With');
header("HTTP/1.1 200 OK");
die();
}
这只是为了发展。这样我就可以等待9毫秒和500毫秒,而不是8秒和500毫秒。我可以这样做,因为生产JS应用程序将在同一台机器上生产,所以没有选项,但开发是我的本地。
其他回答
已经讨论过这个问题,下面是我对这个问题的结论和我的解决方案。
根据CORS策略(强烈建议您阅读它),如果浏览器认为它需要停止发送OPTIONS请求,您不能仅仅强制浏览器停止发送OPTIONS请求。
有两种方法可以解决这个问题:
确保你的请求是“简单请求” 设置OPTIONS请求的Access-Control-Max-Age
简单的请求
一个简单的跨站点请求是一个满足以下所有条件的请求:
唯一允许的方法是:
得到 头 帖子
除了由用户代理(例如Connection, user - agent等)自动设置的头信息外,允许手动设置的头信息有:
接受 接收语言 内容语言 内容类型
Content-Type头唯一允许的值是:
应用程序/ x-www-form-urlencoded 多部分/格式 文本/平原
简单的请求不会引起飞行前选项请求。
为OPTIONS检查设置缓存
您可以为OPTIONS请求设置Access-Control-Max-Age,以便它在过期之前不会再次检查权限。
Access-Control-Max-Age给出了在不发送另一个preflight请求的情况下,对preflight请求的响应可以缓存的时间(以秒为单位)。
限制指出
对于Chrome, Access-Control-Max-Age的最大秒数是600,也就是10分钟,根据Chrome源代码 Access-Control-Max-Age每次只对一个资源有效,例如URL路径相同的GET请求,但不同的查询将被视为不同的资源。因此,对第二个资源的请求仍然会触发预飞行请求。
关于飞行前OPTIONS请求的实际需求,请参考以下答案:CORS -引入飞行前请求的动机是什么?
要禁用OPTIONS请求,ajax请求必须满足以下条件:
请求不设置自定义HTTP报头,如'application/xml'或'application/json'等 请求方法必须是GET、HEAD或POST中的一个。如果是POST,内容类型应该是application/x-www-form-urlencoded、multipart/form-data或text/plain
参考: https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
是的,有可能避免期权请求。选项请求是一个飞行前请求,当你发送(post)任何数据到另一个域。这是浏览器安全问题。但是我们可以使用另一种技术:iframe传输层。我强烈建议您忘记任何CORS配置,并使用现成的解决方案,它将在任何地方工作。
看看这里: https://github.com/jpillora/xdomain
工作示例: http://jpillora.com/xdomain/
你也可以使用API管理器(如开源的Gravitee.io)通过在preflight中操作头来防止前端应用程序和后端服务之间的CORS问题。
用于响应preflight请求的报头,以指示在发出实际请求时可以使用哪些HTTP报头:
内容类型 access-control-allow-header 授权 x-requested-with
并指定"allow-origin" = localhost:4200
当您打开调试控制台并打开禁用缓存选项时,将始终发送预飞行请求(即在每个请求之前)。如果不禁用缓存,预运行请求将只发送一次(每个服务器)。
推荐文章
- 如何使HTTP请求在PHP和不等待响应
- PATCH和PUT请求的主要区别是什么?
- Access-Control-Allow-Origin不允许Origin < Origin >
- 我可以把我所有的http://链接都改成//吗?
- URL为AJAX请求编码一个jQuery字符串
- 如何获得跨源资源共享(CORS)后请求工作
- 编译System.Net.HttpClient的查询字符串
- 摘要认证和基本认证的区别是什么?
- Axios -删除请求与请求体和头?
- 在Firebase的云功能中启用CORS
- 如何在http获取请求设置报头?
- 如何使用Ruby on Rails进行HTTP请求?
- REST API最佳实践:查询字符串中的参数vs请求体中的参数
- Access-Control-Allow-Credentials报头到底做什么?
- Express.js中的res.send和res.json的区别