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


当前回答

在使用代理拦截请求并写入适当的标头的情况下,可以解决这个问题。 在Varnish的特殊情况下,这些将是规则:

if (req.http.host == "CUSTOM_URL" ) {
set resp.http.Access-Control-Allow-Origin = "*";
if (req.method == "OPTIONS") {
   set resp.http.Access-Control-Max-Age = "1728000";
   set resp.http.Access-Control-Allow-Methods = "GET, POST, PUT, DELETE, PATCH, OPTIONS";
   set resp.http.Access-Control-Allow-Headers = "Authorization,Content-Type,Accept,Origin,User-Agent,DNT,Cache-Control,X-Mx-ReqToken,Keep-Alive,X-Requested-With,If-Modified-Since";
   set resp.http.Content-Length = "0";
   set resp.http.Content-Type = "text/plain charset=UTF-8";
   set resp.status = 204;
}

}

其他回答

编辑2018-09-13:在这个响应的末尾增加了关于这个飞行前请求以及如何避免它的一些精度。

OPTIONS请求是我们在跨源资源共享(CORS)中所谓的飞行前请求。

当您在特定情况下跨不同来源提出请求时,它们是必要的。

某些浏览器会发出这种预运行请求,作为一种安全措施,以确保正在执行的请求是受服务器信任的。 这意味着服务器理解在请求上发送的方法、源和头是安全的。

当您试图执行跨源请求时,您的服务器不应该忽略这些请求,而是应该处理这些请求。

好的资源可以在这里找到http://enable-cors.org/

处理这些问题的一种方法是确保对于任何具有OPTIONS方法的路径,服务器都会发送带有此报头的响应

Access-Control-Allow-Origin: *

这将告诉浏览器服务器愿意回答来自任何来源的请求。

有关如何向服务器添加CORS支持的详细信息,请参阅以下流程图

http://www.html5rocks.com/static/images/cors_server_flowchart.png


编辑2018-09-13

CORS OPTIONS请求仅在某些情况下被触发,如MDN文档中所解释的:

Some requests don’t trigger a CORS preflight. Those are called “simple requests” in this article, though the Fetch spec (which defines CORS) doesn’t use that term. A request that doesn’t trigger a CORS preflight—a so-called “simple request”—is one that meets all the following conditions: The only allowed methods are: GET HEAD POST Apart from the headers set automatically by the user agent (for example, Connection, User-Agent, or any of the other headers with names defined in the Fetch spec as a “forbidden header name”), the only headers which are allowed to be manually set are those which the Fetch spec defines as being a “CORS-safelisted request-header”, which are: Accept Accept-Language Content-Language Content-Type (but note the additional requirements below) DPR Downlink Save-Data Viewport-Width Width The only allowed values for the Content-Type header are: application/x-www-form-urlencoded multipart/form-data text/plain No event listeners are registered on any XMLHttpRequestUpload object used in the request; these are accessed using the XMLHttpRequest.upload property. No ReadableStream object is used in the request.

我以前用过的一个解决方案——假设你的网站在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网站上-你可以进行同源请求,不需要任何选项请求:)

不能,但可以使用JSONP避免CORS。

是的,有可能避免期权请求。选项请求是一个飞行前请求,当你发送(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