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

使用Symfony RetryableHttpClient获取错误响应内容为空的问题

Symfony RetryableHttpClient无法获取400/500错误响应内容的解决方法

问题描述

使用Symfony的RetryableHttpClient和AsyncResponse时,无法获取400/500错误状态码对应的响应内容:

  • 直接调用getContent(false)(参数false表示不对错误状态码抛异常),返回内容为空
  • 在try/catch块中捕获ClientExceptionInterface或ServerExceptionInterface后,调用异常对象中响应的getContent(false),返回内容依然为空

但用Postman测试相同请求时,能正常获取预期的JSON格式错误响应。

示例代码

V1 直接调用getContent(false)

/* @var Symfony\Component\HttpClient\RetryableHttpClient $client */
$response = $client->request('POST', '/something' , [
    'auth_bearer' => '******',
    'body' => [
        "some" => "thing"
    ]
]);

/* @var Symfony\Component\HttpClient\Response\AsyncResponse $response */
p_r($response->getContent(false)); // 返回空内容

V2 try/catch捕获异常后获取内容

try {
    // 同V1的请求代码
    $response->getContent(); // 抛出异常
} catch (ClientExceptionInterface|ServerExceptionInterface $exception) {
    p_r($exception->getResponse()->getContent(false)); // 返回空内容
}

问题原因

RetryableHttpClient默认会对4xx/5xx状态码的请求进行重试,重试过程中原始的错误响应内容会被丢弃,导致后续无法读取到完整的错误响应。

解决方法

方法1:自定义重试策略,排除目标状态码

通过实现RetryStrategyInterface自定义重试逻辑,让指定的400/500状态码不触发重试,保留原始响应内容。

步骤1:创建自定义重试策略类

use Symfony\Component\HttpClient\Retry\RetryStrategyInterface;
use Symfony\Contracts\HttpClient\ResponseInterface;

class CustomRetryStrategy implements RetryStrategyInterface
{
    private $defaultStrategy;

    public function __construct(RetryStrategyInterface $defaultStrategy)
    {
        $this->defaultStrategy = $defaultStrategy;
    }

    public function shouldRetry(ResponseInterface $response, float $delay): bool
    {
        $statusCode = $response->getStatusCode();
        // 对400、500状态码不重试,直接返回原始响应
        if (in_array($statusCode, [400, 500])) {
            return false;
        }
        // 其他状态码沿用默认重试逻辑
        return $this->defaultStrategy->shouldRetry($response, $delay);
    }

    public function getDelay(ResponseInterface $response): float
    {
        return $this->defaultStrategy->getDelay($response);
    }
}

步骤2:初始化RetryableHttpClient时使用自定义策略

use Symfony\Component\HttpClient\RetryableHttpClient;
use Symfony\Component\HttpClient\NativeHttpClient;
use Symfony\Component\HttpClient\Retry\DefaultRetryStrategy;

// 创建默认重试策略
$defaultStrategy = new DefaultRetryStrategy();
// 包装为自定义策略
$customStrategy = new CustomRetryStrategy($defaultStrategy);
// 初始化带有自定义策略的RetryableHttpClient
$client = new RetryableHttpClient(new NativeHttpClient(), $customStrategy);

方法2:通过on_progress回调实时捕获响应内容

在请求选项中添加on_progress回调,在响应传输过程中直接收集内容,避免重试导致的内容丢失。

$responseContent = '';
$response = $client->request('POST', '/something', [
    'auth_bearer' => '******',
    'body' => [
        "some" => "thing"
    ],
    'on_progress' => function (int $dlNow, int $dlSize, array $info) use (&$responseContent) {
        // 实时拼接响应内容
        if (!empty($info['response_content'])) {
            $responseContent .= $info['response_content'];
        }
    }
]);

// 无论状态码是否错误,$responseContent都会保留完整响应内容
p_r($responseContent);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 05:25:20