OVH主机PHP流式传输失效问题求助
解决OVH主机上OpenAI流式传输失效问题
问题背景
我开发了一款基于OpenAI API的聊天应用,本地环境中通过proxy.php后端实现了数据流式传输,前端React可实时显示消息逐段生成效果。但部署到OVH基础个人主机后,流式传输功能失效,仅能在消息完全生成后收到完整内容,严重影响用户体验。尝试配置.htaccess文件未解决问题,相关代码如下:
现有proxy.php代码
<?php ob_implicit_flush(true); // Log all request details file_put_contents('debug.log', print_r($_SERVER, true) . "\n\n" . file_get_contents('php://input') . "\n\n", FILE_APPEND); // Liste des origines autorisées $allowed_origins = array( 'https://philogpt.vmirebeau.fr', 'http://localhost:3000', 'http://localhost' ); // Détecter l'origine de la requête $origin = $_SERVER['HTTP_ORIGIN'] ?? ''; if (in_array($origin, $allowed_origins)) { header("Access-Control-Allow-Origin: " . $origin); } else { // Par défaut, interdire l'accès si l'origine n'est pas autorisée header("Access-Control-Allow-Origin: null"); } header("Access-Control-Allow-Methods: POST, GET, OPTIONS"); header("Access-Control-Allow-Headers: Content-Type, Authorization"); if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') { exit(0); } // Récupérer les données JSON $json_data = file_get_contents('php://input'); $data = json_decode($json_data, true); // Vérifier si la clé 'input' existe dans les données JSON if (!isset($data['input'])) { http_response_code(400); // Bad Request echo "Champ 'input' manquant dans les données JSON."; exit; } // Récupérer et assigner la valeur de 'input' $input = $data['input']; header('Content-Type: application/json'); // Lire la clé API à partir de la variable d'environnement $api_key = MY_API_KEY; if (!$api_key) { http_response_code(500); // Internal Server Error echo "Clé API non trouvée."; exit; } // Préparer les données de la requête à envoyer à l'API GPT $data = array( 'model' => 'gpt-4o-mini', 'stream' => true, 'messages' => $input // Transmettre directement l'historique des messages reçu dans 'input' ); // Définir les options curl pour la requête API $options = array( CURLOPT_URL => 'https://api.openai.com/v1/chat/completions', CURLOPT_RETURNTRANSFER => true, CURLOPT_POSTFIELDS => json_encode($data), CURLOPT_HTTPHEADER => array( 'Content-Type: application/json', 'Authorization: Bearer ' . $api_key ), // Traiter chaque fragment de données au fur et à mesure qu'il arrive CURLOPT_WRITEFUNCTION => function($ch, $chunk) { echo $chunk; return strlen($chunk); } ); // Initialiser la requête curl $ch = curl_init(); // Définir les options curl spécifiées précédemment curl_setopt_array($ch, $options); // Exécuter la requête curl et fermer la connexion curl_exec($ch); curl_close($ch); ?>
尝试的.htaccess配置
<IfModule mod_proxy_http.c> SetEnv proxy-sendchunked 1 # Disable buffering for this route SetEnvIf Request_URI “^/server/proxy.php” proxy-sendchunked </IfModule> # Disable compression to avoid interfering with streaming <IfModule mod_deflate.c> SetEnv no-gzip 1 </IfModule> # Enable CORS requests if necessary <IfModule mod_headers.c> Header always set Access-Control-Allow-Origin “*” Header always set Access-Control-Allow-Methods “POST, GET, OPTIONS” Header always set Access-Control-Allow-Headers “Content-Type” </IfModule> # Avoid caching for proxy responses <IfModule mod_headers.c> Header set Cache-Control “no-store, no-cache, must-revalidate, max-age=0” </IfModule>
解决方案
1. 强制禁用PHP与服务器输出缓冲
OVH主机默认开启多层输出缓冲,仅ob_implicit_flush(true)不足以生效。替换原代码开头的缓冲设置为:
// 彻底禁用所有输出缓冲 ob_end_flush(); while (ob_get_level() > 0) { ob_end_flush(); } ob_implicit_flush(true); // 配置PHP核心参数禁用缓冲 ini_set('output_buffering', 'off'); ini_set('zlib.output_compression', false); ini_set('implicit_flush', true); ini_set('max_execution_time', 300); // 延长超时时间适配长对话 // 发送头部指令告知服务器不缓冲 header('X-Accel-Buffering: no'); header('Cache-Control: no-cache, no-store, must-revalidate'); header('Pragma: no-cache'); header('Connection: keep-alive');
2. 修复cURL流式输出配置
原CURLOPT_RETURNTRANSFER => true会让cURL将响应暂存内存,无法实时输出。修改cURL选项:
$options = array( CURLOPT_URL => 'https://api.openai.com/v1/chat/completions', CURLOPT_RETURNTRANSFER => false, // 关键:不返回内容,直接输出到客户端 CURLOPT_POSTFIELDS => json_encode($data), CURLOPT_HTTPHEADER => array( 'Content-Type: application/json', 'Authorization: Bearer ' . $api_key ), CURLOPT_WRITEFUNCTION => function($ch, $chunk) { echo $chunk; flush(); // 强制刷新输出到客户端 return strlen($chunk); }, CURLOPT_TIMEOUT => 300 // 匹配PHP超时时间 );
3. 修正.htaccess配置(替换原有内容)
原配置存在中文引号语法错误,且规则不够精准。使用以下配置:
<IfModule mod_headers.c> # 禁用服务器层缓冲 Header set X-Accel-Buffering "no" # 禁用压缩避免流式响应被合并 Header set Content-Encoding "identity" # 强制禁止缓存 Header set Cache-Control "no-store, no-cache, must-revalidate, max-age=0" Header set Pragma "no-cache" # 精准配置CORS(与PHP代码保持一致,避免冲突) SetEnvIfOrigin "https://philogpt.vmirebeau.fr|http://localhost:3000|http://localhost" AccessControlAllowOrigin=$0 Header set Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin Header set Access-Control-Allow-Methods "POST, GET, OPTIONS" Header set Access-Control-Allow-Headers "Content-Type, Authorization" </IfModule> <IfModule mod_deflate.c> # 仅对proxy.php禁用压缩 SetEnvIf Request_URI "^/server/proxy.php$" no-gzip </IfModule> <IfModule mod_expires.c> # 关闭过期缓存 ExpiresActive Off </IfModule> # 禁用mod_proxy相关缓冲(若主机启用) <IfModule mod_proxy_http.c> SetEnvIf Request_URI "^/server/proxy.php$" proxy-sendchunked=1 </IfModule>
4. 检查OVH主机额外限制
- 登录OVH控制面板,检查是否启用
mod_security模块,若启用可临时关闭测试,或添加规则允许流式响应。 - 确认主机PHP版本为7.4+,低版本可能不支持部分缓冲控制指令。
- 若使用OVH的CDN或缓存服务,需将
proxy.php路径加入缓存白名单,禁止CDN缓冲该路径的响应。
内容的提问来源于stack exchange,提问作者Vivien Mirebeau
相关产品推荐
相关产品推荐

