You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.htaccess重写规则导致PHP中Server-Sent Events(SSE)失效

解决PHP SSE与.htaccess重写规则兼容的问题

方案一:让SSE脚本绕过重写路由

如果不需要通过应用入口处理SSE请求,最简单的办法是修改.htaccess,让你的SSE脚本直接被访问,不经过index.php:

# 优先匹配SSE脚本,直接放行
RewriteRule ^sse\.php$ - [L]

# 原有重写规则
RewriteCond %{REQUEST_URI} !favicon.ico(.*)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)?$ index.php [QSA,L]

把sse.php换成你实际的SSE脚本文件名,[L]标记会让匹配到的请求跳过后续重写规则,直接访问脚本本身,避开应用内部的缓冲、会话锁等干扰。

方案二:在应用入口处理SSE请求(需保留路由)

如果必须让SSE请求经过index.php(比如需要权限验证),要在入口文件最开头拦截SSE请求,提前处理缓冲和会话问题:

// index.php 最顶部添加
if (strpos($_SERVER['REQUEST_URI'], '/sse') !== false) {
    // 强制关闭所有输出缓冲
    ini_set('output_buffering', 'off');
    while (ob_get_level() > 0) {
        ob_end_clean();
    }

    // 释放会话锁(如果应用启用了session)
    if (session_status() === PHP_SESSION_ACTIVE) {
        session_write_close();
    }

    // 引入你的SSE逻辑
    require_once __DIR__ . '/path/to/your-sse-script.php';
    exit; // 必须终止后续代码执行,避免应用逻辑干扰
}

// 原有应用初始化代码...

为什么路由到index.php会失效?

核心原因是应用入口的全局逻辑会破坏SSE的运行条件:

  • 输出缓冲:多数PHP应用/框架会在入口开启全局输出缓冲(ob_start()),即使SSE脚本里关闭缓冲,入口的缓冲已经存在,导致数据无法即时flush到客户端。
  • 会话锁:如果应用在入口启动了session_start(),会话文件会被独占锁定,直到脚本结束或手动释放锁,这会阻塞SSE的循环输出。
  • 中间件干扰:路由、日志、响应处理等中间件可能会修改响应头、添加额外输出,破坏SSE要求的text/event-stream格式和长连接状态。

额外注意事项

  • 检查服务器配置:Apache的Timeout不要设得太短(至少大于SSE的运行时长),Nginx需设置proxy_read_timeout 300s;(或更长)支持长连接。
  • 确保SSE的响应头不被覆盖:应用的响应类或中间件可能会重写Content-Type,要保证text/event-stream最终生效。
  • 用浏览器开发者工具排查:在Network面板查看SSE请求的响应头,确认Cache-Control、Connection等头是否符合要求,同时观察数据流是否持续输出。

内容的提问来源于stack exchange,提问作者Pablo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 21:44:52