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


当前回答

当您打开调试控制台并打开禁用缓存选项时,将始终发送预飞行请求(即在每个请求之前)。如果不禁用缓存,预运行请求将只发送一次(每个服务器)。

其他回答

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

在之前的文章中已经提到过,OPTIONS请求的存在是有原因的。如果您的服务器响应时间过长(例如海外连接),您也可以让浏览器缓存飞行前请求。

让你的服务器用Access-Control-Max-Age报头来回复,对于到达同一端点的请求,preflight请求将被缓存,不再发生。

在花了一整天半的时间试图解决类似的问题后,我发现这与IIS有关。

我的Web API项目是这样建立的:

// WebApiConfig.cs
public static void Register(HttpConfiguration config)
{
    var cors = new EnableCorsAttribute("*", "*", "*");
    config.EnableCors(cors);
    //...
}

我在网上没有CORS特定的配置选项。配置>系统。webServer节点,就像我在很多帖子中看到的那样

全局中没有特定于CORS的代码。Asax或在控制器中作为装饰器

问题在于应用程序池设置。

托管管道模式被设置为经典(更改为集成),标识被设置为网络服务(更改为ApplicationPoolIdentity)

更改这些设置(并刷新应用程序池)为我解决了这个问题。

对我有用的是导入“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配置。

你也可以使用API管理器(如开源的Gravitee.io)通过在preflight中操作头来防止前端应用程序和后端服务之间的CORS问题。

用于响应preflight请求的报头,以指示在发出实际请求时可以使用哪些HTTP报头:

内容类型 access-control-allow-header 授权 x-requested-with

并指定"allow-origin" = localhost:4200