浏览器之间在实现预检缓存的方式上存在差异。不幸的是,仅 W3C 规范并不能解释您在飞行前缓存中观察到的细微差别。
对于阅读此问题的其他人,我想解释一下当 OP 说 飞行前请求时,他指的是在跨域 POST 请求之前的 OPTIONS 请求。 OPTIONS 请求用于查询 API 并确定允许哪些 HTTP 方法用于跨域请求。通常,您希望看到对 OPTIONS 请求的这种类型的响应:
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: Content-Type, X-Requested-With
Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE, PUT
由于您使用的是 Google Chrome,我将向您推荐 Webkit 源代码的适用部分:
https://github.com/WebKit/webkit/blob/master/Source/WebCore/loader/CrossOriginPreflightResultCache.cpp
默认的预检缓存超时为 5 秒:
static const auto defaultPreflightCacheTimeout = std::chrono::seconds(5);
最大值为 5 分钟:
static const auto maxPreflightCacheTimeout = std::chrono::seconds(600);
服务器可以使用响应标头中的 Access-Control-Max-Age 字段为飞行前请求指定超时值,但是 Webkit 浏览器强制最大超时为 5分钟。
回答您的问题:
我怎样才能避免每次飞行前的请求?
您需要在对OPTIONS 请求的 API 响应的标头中将 Access-Control-Max-Age 设置为 600。
这个时间间隔是多少?
对于 Webkit 浏览器(即 Google Chrome),默认超时值为 5 秒。这就是为什么您会在每个 POST 请求之前看到飞行前请求,但如果您快速提交 POST 请求,则不会看到额外的飞行前请求。
这是 Chrome 浏览器特有的吗?
是的,不同浏览器在如何实现预检缓存方面存在差异。 W3C 规范并未指定在 Web 浏览器中构建飞行前缓存功能所需的所有内容。