我正在构建一个web API。我发现每当我使用Chrome POST, GET到我的API,总是有一个选项请求发送之前的真正的请求,这是相当恼人的。目前,我让服务器忽略任何OPTIONS请求。现在我的问题是,发送一个OPTIONS请求来增加服务器的负载有什么好处呢?有没有办法完全停止浏览器发送OPTIONS请求?


当前回答

已经讨论过这个问题,下面是我对这个问题的结论和我的解决方案。

根据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请求,但不同的查询将被视为不同的资源。因此,对第二个资源的请求仍然会触发预飞行请求。

其他回答

是的,有可能避免期权请求。选项请求是一个飞行前请求,当你发送(post)任何数据到另一个域。这是浏览器安全问题。但是我们可以使用另一种技术:iframe传输层。我强烈建议您忘记任何CORS配置,并使用现成的解决方案,它将在任何地方工作。

看看这里: https://github.com/jpillora/xdomain

工作示例: http://jpillora.com/xdomain/

关于飞行前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

我以前用过的一个解决方案——假设你的网站在mydomain.com上,你需要向foreigndomain.com发送一个ajax请求

配置IIS重写从您的域到外部域-例如。

<rewrite>
  <rules>
    <rule name="ForeignRewrite" stopProcessing="true">
        <match url="^api/v1/(.*)$" />
        <action type="Rewrite" url="https://foreigndomain.com/{R:1}" />
    </rule>
  </rules>
</rewrite>

在你的mydomain.com网站上-你可以进行同源请求,不需要任何选项请求:)

对我有用的是导入“github.com/gorilla/handlers”,然后这样使用它:

router := mux.NewRouter()
router.HandleFunc("/config", getConfig).Methods("GET")
router.HandleFunc("/config/emcServer", createEmcServers).Methods("POST")

headersOk := handlers.AllowedHeaders([]string{"X-Requested-With", "Content-Type"})
originsOk := handlers.AllowedOrigins([]string{"*"})
methodsOk := handlers.AllowedMethods([]string{"GET", "HEAD", "POST", "PUT", "OPTIONS"})

log.Fatal(http.ListenAndServe(":" + webServicePort, handlers.CORS(originsOk, headersOk, methodsOk)(router)))

一旦我执行了Ajax POST请求并将JSON数据附加到它,Chrome总是会添加内容类型头,这不是在我以前的AllowedHeaders配置。

OPTIONS请求是web浏览器的一个特性,所以要禁用它并不容易。但我找到了用代理转移的方法。如果服务端点还不能处理CORS/OPTIONS,可能还在开发中,或者配置错误,那么它就很有用。

步骤:

使用工具(nginx, YARP,…)为这些请求设置反向代理。 创建一个端点来处理OPTIONS请求。创建一个普通的空端点可能更容易,并确保它能很好地处理CORS。 为代理配置两组规则。一种是将所有OPTIONS请求路由到上面的虚拟端点。另一个是将所有其他请求路由到实际的问题端点。 更新网站以使用代理代替。

基本上这种方法是欺骗浏览器,选项请求工作。考虑到CORS并不是为了加强安全,而是为了放松同源政策,我希望这招能管用一段时间。:)