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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 05:10:54