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

PHP实现无需等待响应的HTTPS POST请求(Fire and Forget)失效问题

PHP实现无依赖的Fire-and-Forget POST请求(支持HTTPS)

原代码在HTTP模式下正常,但HTTPS模式失效,核心原因是fsockopen连接HTTPS端口时未建立TLS加密通道,直接发送明文HTTP请求会被服务器拒绝。以下是修复后的完整实现:

修复后的代码

private function sendRequestAndForget(string $method, string $url, array $params = []): void
{
    $parts = parse_url($url);
    if ($parts === false)
        throw new Exception('Unable to parse URL');
    $host = $parts['host'] ?? null;

    $isHttps = ($parts['scheme'] === 'https');
    $port = $parts['port'] ?? ($isHttps ? 443 : 80);
    $path = $parts['path'] ?? '/';
    $query = $parts['query'] ?? '';
    parse_str($query, $queryParts);

    if ($host === null)
        throw new Exception('Unknown host');

    // 建立TLS加密连接(HTTPS核心修复)
    $socketContext = stream_context_create([
        'ssl' => [
            'verify_peer' => false, // 生产环境建议设为true并配置CA证书
            'verify_peer_name' => false,
        ]
    ]);
    $connectionString = ($isHttps ? 'tls://' : '') . $host . ':' . $port;
    $connection = stream_socket_client(
        $connectionString,
        $errno,
        $errstr,
        30,
        STREAM_CLIENT_CONNECT,
        $socketContext
    );

    if ($connection === false)
        throw new Exception('Unable to connect to ' . $host . ": $errstr ($errno)");
    $method = strtoupper($method);

    if (!in_array($method, ['POST', 'PUT', 'PATCH'], true)) {
        $queryParts = $params + $queryParts;
        $params = [];
    }

    // 构建HTTP请求
    $request = $method . ' ' . $path;
    if ($queryParts) {
        $request .= '?' . http_build_query($queryParts);
    }
    $request .= ' HTTP/1.1' . "\r\n";
    $request .= 'Host: ' . $host . "\r\n";
    $request .= 'Connection: Close' . "\r\n";

    $body = json_encode($params);
    if ($body) {
        $request .= 'Content-Type: application/json' . "\r\n";
        $request .= 'Content-Length: ' . strlen($body) . "\r\n";
    }
    $request .= "\r\n"; // HTTP头部结束标记
    $request .= $body;

    // 发送后立即关闭连接,实现真正的"发后即忘"
    fwrite($connection, $request);
    stream_set_blocking($connection, false); // 非阻塞模式避免等待响应
    fclose($connection);
}

关键修改说明

  1. TLS加密处理:

    • 用stream_socket_client替代fsockopen,通过tls://前缀强制HTTPS连接使用加密通道
    • SSL上下文配置:生产环境需开启verify_peer和verify_peer_name,并指定CA证书路径以避免安全风险
  2. 确保无等待逻辑:

    • 添加stream_set_blocking($connection, false),防止写入或关闭连接时阻塞等待服务器响应
    • 发送请求后立即关闭连接,不读取任何服务器返回内容
  3. HTTP规范修正:

    • 调整Connection: Close位置,确保服务器正确识别连接关闭指令
    • 严格遵循HTTP协议的头部结束空行格式

测试验证

调用该方法后,你的测试脚本中的sleep(5000)不会阻塞发起请求的脚本,发起方会立即返回,测试脚本将在后台独立执行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 03:08:26