跨域接口每发一次请求前都先来一次 OPTIONS,Network 面板里一半请求是预检。响应里带了 Access-Control-Max-Age: 600,第二次还是照发。碰到这种情况,我一般先确认改动有没有真的生效。
原因不复杂,预检缓存按 URL 加请求方法加请求头组合存,实际请求带了自定义头比如 Authorization,预检的 Allow-Headers 没列全,浏览器认为缓存不适用。Max-Age 超过浏览器自己的上限也会被截断。
「预检缓存」相关的日志我一般连着看前后五分钟,单看一条报错经常判断不出是哪一步失败。日志级别临时调高可以,记得改回去,长期开着既占磁盘又掩盖真问题。
curl -i -X OPTIONS https://api.example.com/v1/orders \ -H 'Origin: https://app.example.com' \ -H 'Access-Control-Request-Headers: authorization,content-type'
权限不要一口气开到最大,先加到够用再往上试,范围小才好收。
具体做法是,确认 Access-Control-Allow-Headers 覆盖实际发送的全部自定义头;Max-Age 设成 600 到 3600 之间 别超过浏览器上限;预检响应只按 Origin 变化 不要带多余的 Vary 头 避免缓存键对不上;用同一个 Origin 连发两次请求 看第二次是否还有 OPTIONS。
最后用这个标准收尾,刷新页面后同一接口十分钟内只出现一次 OPTIONS 后续直接发正式请求。
