关键在于Apache正确返回Access-Control-Max-Age并确保其出现在OPTIONS响应中,必须用Header always set绑定到块,同时避免后端重复处理、确保Origin及请求特征一致、中间链路透传该头。

要让浏览器少发 OPTIONS 请求、加快跨域响应,关键不是“加速单次预检”,而是让预检结果被有效缓存——核心在于 Apache 正确返回 Access-Control-Max-Age,并确保该头出现在 OPTIONS 响应中。
必须用 Header always set 绑定到 OPTIONS 方法
普通 Header set 对 OPTIONS 响应无效,因为 Apache 默认不把这类头注入由内部模块(如静态文件处理或 mod_proxy)生成的 204/200 响应。正确做法是限定作用范围,并强制注入:
- 在虚拟主机或目录配置中启用
mod_headers - 用
明确只针对预检请求生效 - 所有 CORS 头都加
always:包括Access-Control-Allow-Origin、Access-Control-Allow-Methods、Access-Control-Allow-Headers和最关键的Access-Control-Max-Age
示例配置:
Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Methods "GET,POST,PUT,DELETE,OPTIONS"
Header always set Access-Control-Allow-Headers "Content-Type,Authorization,X-Requested-With"
Header always set Access-Control-Max-Age "86400"
避免后端与 Apache 的 CORS 响应冲突
如果后端框架(如 Express、Django REST Framework)也自动处理 OPTIONS,会导致重复响应或头缺失,浏览器可能拒绝缓存。必须统一响应出口:
- Apache 截断预检时,后端应跳过所有 OPTIONS 处理逻辑
- Express 中关闭
cors({ preflightContinue: false })(默认即为 false,但需确认未设为 true) - Django REST Framework 中禁用
CORS_URLS_REGEX对 OPTIONS 的匹配,或在视图层直接 return HttpResponse(status=204)
验证方式:curl -I -X OPTIONS http://yoursite/api/xxx,响应应为 204 或 200,且只含 Apache 显式设置的头,无重复或缺失。
Apache Superset 是一个广泛采用的开源 BI 平台,用于 SQL 探索、图表构建和仪表板交付。当代理需要查询仓库数据、组装仪表板或使用成熟的分析界面解释指标而不是临时笔记本代码时,此技能非常有用。
确保缓存实际生效的三个前提
即使设置了 Access-Control-Max-Age,浏览器仍可能忽略缓存。以下任一不满足,预检都会重发:
- 请求中的
Origin必须与上次预检完全一致(协议、域名、端口) - 实际请求的方法(如 PUT)和头字段(如
Authorization)必须与预检时声明的一致 - 中间链路(CDN、反向代理、负载均衡器)不能过滤、覆盖或删除
Access-Control-Max-Age头
若使用 CDN,需显式配置其透传该头;若用 Nginx 做前置代理,需添加 proxy_pass_request_headers on; 并检查是否启用了 underscores_in_headers 导致头被丢弃。
动态 Origin 时的注意事项
若不能设 Access-Control-Allow-Origin "*"(例如需支持 credentials),则必须动态反射 Origin,但必须严格校验:
- 用
%{HTTP:Origin}e变量配合白名单判断,禁止无条件回写 - 此时
Access-Control-Allow-Credentials可设为true,但Access-Control-Allow-Origin不能为* - 动态头必须仍带
always,否则 OPTIONS 响应中不会出现
错误示例:Header set Access-Control-Allow-Origin "%{HTTP:Origin}e" —— 缺少 always,且无校验,存在安全风险。










