为啥 GuzzleHttp 客户端在 Laravel/Lumen 上使用它发出网络请求时会抛出 ClientException?
Posted
技术标签:
【中文标题】为啥 GuzzleHttp 客户端在 Laravel/Lumen 上使用它发出网络请求时会抛出 ClientException?【英文标题】:Why GuzzleHttp client throws ClientException when using it to make network request on Laravel/Lumen?为什么 GuzzleHttp 客户端在 Laravel/Lumen 上使用它发出网络请求时会抛出 ClientException? 【发布时间】:2019-10-15 15:39:54 【问题描述】:我目前正在使用 Laravel/Lumen 微框架构建一个金融微服务应用程序。一切都按预期完美运行。我现在的问题是我正在尝试使用GuzzleHttp
客户端通过来自ApiGateway
的Api 调用向我的内部服务发出网络请求。问题是当我向内部服务发出请求时,它总是抛出 ClientException 异常。
客户端异常。
客户端错误:
GET http://127.0.0.1:8081/v1/admin
导致401 Unauthorized
响应:"error":"Unauthorized.","code":401
我尝试使用 postman 向相同的内部服务发出网络请求;它工作正常。但是,由于某种原因仍然无法使用GuzzleHttp
。我不知道我做错了什么。我们将不胜感激。
这里是 ApiGateway 中的 httpClient.php。
//Constructor method
public function __construct()
$this->baseUri = config('services.auth_admin.base_uri');
public function httpRequest($method, $requestUrl, $formParams = [], $headers = [])
//Instantiate the GazzleHttp Client
$client = new Client([
'base_uri' => $this->baseUri,
]);
//Send the request
$response = $client->request($method, $requestUrl, ['form_params' => $formParams, 'headers' => $headers]);
//Return a response
return $response->getBody();
//Internal Service Communication in ApiGateway**
public function getAdmin($header)
return $this->httpRequest('GET', 'admin', $header);
InternalServiceController.php
public function getAdmin(Request $request)
return $this->successResponse($this->authAdminService->getAdmin($request->header()));
我正在使用 Lumen 版本:5.8 和 GuzzleHttp 版本:6.3
【问题讨论】:
401 错误表示您未通过身份验证,听起来您需要将 API 令牌与请求一起发送。 这就是我困惑的原因;当我 dd($request->header()) 并且内部客户端期望令牌位于请求标头上时,请求标头包含有效令牌。 你能把传递给方法的 headers 数组包含进去吗? 你能把 $client->request($method, $requestUrl, ['form_params' => $formParams, 'headers' => $headers]) 改成 $client->request($method , $requestUrl, ['query' => $formParams, 'headers' => $headers]) 当你使用 GET 方法时? API是否需要json格式的数据?如果是,您是否将 application/json 作为内容类型传递?如果仍然是,那么使用form_params
将无济于事。您应该改用json
。除此之外,身份验证是基本的吗?如果是,那么您的标题应该是这种格式,$header['Authorization'] = "Basic ".base64_encode('your_api_key:your_api_secret_here');
【参考方案1】:
我在这里做了一些假设,希望对你有所帮助。
php 不支持跳过可选参数,因此您应该在调用httpRequest()
时传递一个空数组[]。
public function httpRequest($method, $requestUrl, $formParams = [], $headers = [], $type='json', $verify = false)
//Instantiate the GazzleHttp Client
$client = new Client([
'base_uri' => $this->baseUri,
]);
//the request payload to be sent
$payload = [];
if (!$verify)
$payload['verify'] = $verify; //basically for SSL and TLS
//add the body to the specified payload type
$payload[$type] = $formParams;
//check if any headers have been passed and add it as well
if(count($headers) > 0)
$payload['headers'] = $headers;
//Send the request
$response = $client->request($method, $requestUrl, $payload);
//Return a response
return $response->getBody();
现在你需要在不传入任何form_params或body的时候以这种方式调用它
//Internal Service Communication in ApiGateway**
public function getAdmin($header)
return $this->httpRequest('GET', 'admin', [], $header);
【讨论】:
【参考方案2】:您将标题作为 formParams 传递(第三个索引而不是第四个)。
试试下面:
return $this->httpRequest('GET', 'admin', [], $header);
【讨论】:
是的,我完全理解;我试过了,还是不行。 您能否更新您的示例,以便我们看到您理解? - 很难根据有错误的示例代码提供帮助 感谢您的回答;当时非常有帮助;我刚回来接受你的回答。以上是关于为啥 GuzzleHttp 客户端在 Laravel/Lumen 上使用它发出网络请求时会抛出 ClientException?的主要内容,如果未能解决你的问题,请参考以下文章