我正在构建一个使用 CORS 的 REST 应用程序。每个 REST 调用都是不同的,我发现获取预检 OPTIONS 调用会产生很大的开销。有没有办法缓存并应用预检选项结果,以便对同一域的任何后续调用都使用缓存的响应?
预检只能应用于请求,不能应用于整个域。我在邮件列表中提出了同样的问题,并且存在安全问题。这是整个线程:http://lists.w3.org/Archives/Public/public-webapps/2012AprJun/0228.html
如果您想限制预检请求的数量,需要考虑一些事项。首先请注意,基于 WebKit 的浏览器将最大预检缓存生命周期设置为 10 分钟:
https://github.com/WebKit/webkit/blob/master/Source/WebCore/loader/CrossOriginPreflightResultCache.cpp 基于 Blink 的浏览器将缓存限制为两个小时: https://source.chromium.org/chromium/chromium/src/+/main:services/network/cors/preflight_result.cc;l=40;drc=098756533733ea50b2dcb1c40d9a9e18d49febbe
(我不确定其他浏览器是否也是如此)。因此,虽然您应该始终设置 Access-Control-Max-Age 标头。
接下来请注意,不可能避免 PUT/DELETE 请求的预检。因此,对 API 的更新/删除至少需要每 10 分钟进行一次预检。
在 GET/POST 上,尽可能避免自定义标头,因为它们仍然会触发预检。如果您的请求具有 JSON 正文,请注意“application/json”的 Content-Type(在请求中,而不是响应中)也会触发预检。
如果您愿意改变 API 的“RESTful”程度,您还可以尝试其他一些方法。一种是使用不需要预检的内容类型,例如“text/plain”。自定义标头始终会触发预检,因此如果您有任何自定义标头,您可以将它们移至查询参数中。在最极端的情况下,您可以使用 JSON-RPC 等协议,其中所有请求都发送到单个端点。
老实说,由于浏览器的预检缓存限制为 10/120 分钟,以及 REST 的资源 URL,预检缓存的价值有限。在长时间运行的应用程序过程中,您几乎无法限制预检。我希望 CORS 规范的作者将来能够尝试解决这个问题。
尝试使用 xDomain
如果使用 Angular 或 jQuery,设置对我来说非常简单。 在您的应用程序服务器上,添加 proxy.html,如以下链接的帮助中所述。 添加一些引用“客户端”和中提琴上的 js 文件的标签,不再需要预检。 这包含在 iframe 中以避免需要 cors 检查。
一种方法是您可以将所有 API 调用指向与前端相同的域。在前端服务器上设置 nginx,仅将 API 调用转发到 API 服务器。这将删除所有飞行前通话。