<p>Mercure 正常工作需 Nginx 显式透传关键请求头:Accept、Cache-Control、Connection、Upgrade、Host 及 X-Forwarded-* 系列;响应头需暴露 Link 等字段;FrankenPHP 还须配置 trusted-proxies。</p>

Mercure 依赖特定请求头才能正常工作,Nginx 默认不透传,必须显式配置 proxy_set_header,否则订阅失败、事件无法推送、SSE 连接中断。
必须透传的 Mercure 关键请求头
Mercure(尤其是 FrankenPHP 集成版)在建立 SSE(Server-Sent Events)连接时,会检查客户端是否携带标准协议协商头。Nginx 若未透传,后端 Mercure Hub 会拒绝连接或降级为轮询。
-
Accept:必须透传,Mercure 要求值为text/event-stream,否则返回 406;写法:proxy_set_header Accept $http_accept; -
Cache-Control:Mercure 客户端常设为no-cache,若被 Nginx 清除或覆盖,可能导致连接复用异常;写法:proxy_set_header Cache-Control $http_cache_control; -
Connection和Upgrade:SSE 不依赖 WebSocket 升级,但某些 Mercure 部署(如带 fallback 的网关)会检查这两个头;Nginx 默认丢弃它们,需显式恢复:proxy_set_header Connection $http_connection;、proxy_set_header Upgrade $http_upgrade; -
Host:Mercure Hub 生成事件回调 URL 时需原始 Host;避免用默认 upstream 名,应写:proxy_set_header Host $host;或更安全的proxy_set_header Host $http_host;
X-Forwarded-* 系列不能少,尤其 X-Forwarded-Proto
Mercure 响应中包含的 Link 头(用于自动发现 hub)、重定向 Location、以及事件中的 retry 参数生成逻辑,都依赖客户端原始协议和主机信息。仅透传 Mercure 协议头不够,信任链必须完整。
-
X-Forwarded-Proto:必须设为$scheme,否则 Mercure 返回的Link头里是http://,即使用户访问的是 HTTPS;写法:proxy_set_header X-Forwarded-Proto $scheme; -
X-Forwarded-Host:确保 Mercure 构造的 hub URL 域名正确(比如https://api.example.com/.well-known/mercure),而非内部地址;写法:proxy_set_header X-Forwarded-Host $host; -
X-Forwarded-For:虽 Mercure 不直接校验 IP,但日志、限流、调试都依赖真实客户端 IP;多层代理请用$proxy_add_x_forwarded_for;写法:proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
响应头也要配合:Access-Control-Expose-Headers 和 add_header
Mercure 客户端(JS SDK)需要读取响应中的 Link、Content-Type(必须是 text/event-stream)、Cache-Control 等头。浏览器默认屏蔽非简单响应头,必须显式暴露。
立即学习“PHP免费学习笔记(深入)”;
- 在
location块中添加:add_header 'Access-Control-Expose-Headers' 'Link, Content-Type, Cache-Control, X-RateLimit-Limit, X-RateLimit-Remaining'; - 若前端跨域访问 Mercure hub(如
/.well-known/mercure),还需配Access-Control-Allow-Origin和预检支持;OPTIONS 请求必须 return 204,且含Access-Control-Allow-Headers: Authorization, Accept - 注意:不要用
proxy_hide_header屏蔽Link或Content-Type,Mercure 依赖它们
容易被忽略的 FrankenPHP 特定点
FrankenPHP 内置 Mercure Hub 默认启用 JWT 认证和 CORS,但它**不会自动信任 Nginx 透传的 X-Forwarded-* 头**——它只认直连请求。你必须在 FrankenPHP 配置中显式启用代理信任:
- 启动 FrankenPHP 时加参数:
--mercure.trusted-proxies=127.0.0.1,::1(填 Nginx 所在 IP) - 或通过环境变量:
MERCURE_TRUSTED_PROXIES=127.0.0.1,::1 - 若 Nginx 启用了
underscores_in_headers on;(比如用了X-Mercure-Subscribe这类自定义头),FrankenPHP 默认接受下划线,但 Nginx 必须开这个开关,否则头被静默丢弃



















