我正在构建一个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;
}

}

其他回答

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

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

步骤:

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

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

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

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

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