Symfony 5.4本地API调用外部API返回空引用,Rest Client返回具体400错误
问题排查与解决方案
核心问题分析
- 请求头拼写错误:HttpClient中
carrierDetermination方法的授权头拼写为Autorization(少了字母h),导致外部API无法识别令牌,返回Invalid sender code错误。 - 变量引用错误:控制器中调用
carrierDetermination后,错误使用旧的$response(来自authenticate接口)执行toArray(),若该响应已被消费(流关闭),会触发空引用异常。 - 异常场景下请求数据丢失:HttpClient中添加请求属性的代码在
request()调用之后,若请求抛出异常,该行代码不会执行,导致无法获取请求体数据。
修复步骤
1. 修正Authorization请求头拼写
在carrierDetermination方法中,将错误的请求头名称修正为标准的Authorization:
public function carrierDetermination($params,$infosDossier,$token) { // ... 数据构造逻辑 $response = $this->client->request( "POST", "/external_api_url/carrierDeterminations", [ 'body' => json_encode($data), 'headers' => [ 'Accept' => "*/*", 'Content-Type' => "application/json", 'Authorization' => "Bearer ".$token // 修正拼写 ], 'timeout' => 100, ] ); // ... 后续逻辑 }
2. 修正控制器变量引用
将控制器中carrierDetermination后的$response->toArray()改为$response2->toArray():
// Carrier determination $response2 = $testHttpClient->carrierDetermination($params,$data[0],$token); $bodyData = $request->attributes->get('bodyDataCarrierDetermination'); $data = $response2->toArray(); // 替换为正确的响应对象$response2
3. 提前保存请求体数据(优化异常处理)
将添加请求属性的代码移到request()调用之前,确保请求失败时也能获取到请求体:
public function carrierDetermination($params,$infosDossier,$token) { $data = [ // ... 你的数据结构 ]; array_walk_recursive($data, function (&$item) { $item = strval($item); }); // 提前添加请求体到请求属性 $this->request->getCurrentRequest()->attributes->add(['bodyDataCarrierDetermination' => $data]); $response = $this->client->request( "POST", "/external_api_url/carrierDeterminations", [ 'body' => json_encode($data), 'headers' => [ 'Accept' => "*/*", 'Content-Type' => "application/json", 'Authorization' => "Bearer ".$token ], 'timeout' => 100, ] ); return $response; }
4. 优化异常处理,解析外部API错误信息
在catch块中,确保能正确解析外部API返回的JSON错误:
catch (Exception $e) { if ($e instanceof ClientException) { $errorResponse = $e->getResponse(); try { // 尝试解析JSON格式的错误响应 $errorData = $errorResponse->toArray(); $message = json_encode($errorData); } catch (\Exception $decodeError) { // 解析失败则返回原始响应内容 $message = $errorResponse->getContent(false); } } else { $message = $e->getMessage(); } $bodyData = $request->attributes->get('bodyDataCarrierDetermination', []); return new Response(json_encode([ 'wsel_log_id' => $wsel_log_id, 'request' => $bodyData, 'error' => $message ], $jsonFlags)); }
内容的提问来源于stack exchange,提问作者Budounet
相关产品推荐
相关产品推荐

