使用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_
相关产品推荐
相关产品推荐

