首页 > 解决方案 > Laravel Guzzle - cURL 错误 3:(参见 https://curl.haxx.se/libcurl/c/libcurl-errors.html)

问题描述

我使用 Guzzle 围绕 shopify 的 REST api(使用基本身份验证的私有应用程序)创建了一个简单的包装器:

<?php

namespace App\Services;

use stdClass;
use Exception;
use GuzzleHttp\Client as GuzzleClient;

/**
 * Class ShopifyService
 * @package App\Services
 */
class ShopifyService
{
    /**
     * @var array $config
     */
    private $config = [];

    /**
     * @var GuzzleClient$guzzleClient
     */
    private $guzzleClient;

    /**
     * ShopifyService constructor.
     */
    public function __construct()
    {
        $this->config = config('shopify');
    }

    /**
     * @return ShopifyService
     */
    public function Retail(): ShopifyService
    {
        return $this->initGuzzleClient(__FUNCTION__);
    }

    /**
     * @return ShopifyService
     */
    public function Trade(): ShopifyService
    {
        return $this->initGuzzleClient(__FUNCTION__);
    }

    /**
     * @param string $uri
     * @return stdClass
     * @throws \GuzzleHttp\Exception\GuzzleException
     * @throws Exception
     */
    public function Get(string $uri): stdClass
    {
        $this->checkIfGuzzleClientInitiated();;
        $result = $this->guzzleClient->request('GET', $uri);
        return \GuzzleHttp\json_decode($result->getBody());
    }

    /**
     * @throws Exception
     */
    private function checkIfGuzzleClientInitiated(): void
    {
        if (!$this->guzzleClient) {
            throw new Exception('Guzzle Client Not Initiated');
        }
    }

    /**
     * @param string $storeName
     * @return ShopifyService
     */
    private function initGuzzleClient(string $storeName): ShopifyService
    {
        if (!$this->guzzleClient) {
            $this->guzzleClient = new GuzzleClient([
                'base_url' => $this->config[$storeName]['baseUrl'],
                'auth' => [
                    $this->config[$storeName]['username'],
                    $this->config[$storeName]['password'],
                ],
                'timeout' => 30,
            ]);
        }

        return $this;
    }
}

config/shopify.php看起来像这样的地方:

<?php

use Constants\System;

return [

    System::STORE_RETAIL => [
        'baseUrl' => env('SHOPIFY_API_RETAIL_BASE_URL'),
        'username' => env('SHOPIFY_API_RETAIL_USERNAME'),
        'password' => env('SHOPIFY_API_RETAIL_PASSWORD'),
    ],

    System::STORE_TRADE => [
        'baseUrl' => env('SHOPIFY_API_TRADE_BASE_URL'),
        'username' => env('SHOPIFY_API_TRADE_USERNAME'),
        'password' => env('SHOPIFY_API_TRADE_PASSWORD'),
    ],

];

当我使用这样的服务时:

    $retailShopifySerice = app()->make(\App\Services\ShopifyService::class);

    dd($retailShopifySerice->Retail()->Get('/products/1234567890.json'));

我收到以下错误:

GuzzleHttp\Exception\RequestException cURL 错误 3:(参见https://curl.haxx.se/libcurl/c/libcurl-errors.html

如您所见,我正在使用默认选项(用于基本 uri + 基本身份验证)制作一个简单的 guzzle http 客户端并发出后续 GET 请求。

这在理论上应该可行,但我不知道为什么会抛出这个错误?

我已经验证了配置是否正确(即它具有我期望的值)并尝试清除所有 laravel 缓存。

任何想法这里可能有什么问题?

标签: phplaravelguzzle

解决方案


由于某种原因,我无法base_url选择使用,所以我以不同的方式解决了它:Guzzle\Client

<?php

namespace App\Services;

use Exception;
use App\DTOs\ShopifyResult;
use GuzzleHttp\Client as GuzzleClient;
use GuzzleHttp\Exception\GuzzleException;

/**
 * Class ShopifyService
 * @package App\Services
 */
class ShopifyService
{
    const REQUEST_TYPE_GET = 'GET';
    const REQUEST_TYPE_POST = 'POST';
    const REQUEST_TIMEOUT = 30;

    /**
     * @var array $shopifyConfig
     */
    private $shopifyConfig = [];

    /**
     * ShopifyService constructor.
     */
    public function __construct()
    {
        $this->shopifyConfig = config('shopify');
    }

    /**
     * @param string $storeName
     * @param string $requestUri
     * @return ShopifyResult
     * @throws GuzzleException
     */
    public function Get(string $storeName, string $requestUri): ShopifyResult
    {
        return $this->guzzleRequest(
            self::REQUEST_TYPE_GET,
            $storeName,
            $requestUri
        );
    }

    /**
     * @param string $storeName
     * @param string $requestUri
     * @param array $requestPayload
     * @return ShopifyResult
     * @throws GuzzleException
     */
    public function Post(string $storeName, string $requestUri, array $requestPayload = []): ShopifyResult
    {
        return $this->guzzleRequest(
            self::REQUEST_TYPE_POST,
            $storeName,
            $requestUri,
            $requestPayload
        );
    }

    /**
     * @param string $requestType
     * @param string $storeName
     * @param $requestUri
     * @param array $requestPayload
     * @return ShopifyResult
     * @throws GuzzleException
     * @throws Exception
     */
    private function guzzleRequest(string $requestType, string $storeName, $requestUri, array $requestPayload = []): ShopifyResult
    {
        $this->validateShopifyConfig($storeName);

        $guzzleClient = new GuzzleClient();

        $requestOptions = [
            'auth' => [
                $this->shopifyConfig[$storeName]['username'],
                $this->shopifyConfig[$storeName]['password']
            ],
            'timeout' => self::REQUEST_TIMEOUT,
        ];

        if (count($requestPayload)) {
            $requestOptions['json'] = $requestPayload;
        }

        $response = $guzzleClient->request(
            $requestType,
            $this->shopifyConfig[$storeName]['baseUrl'] . $requestUri,
            $requestOptions
        );

        list ($usedApiCall, $totalApiCallAllowed) = explode(
            '/',
            $response->getHeader('X-Shopify-Shop-Api-Call-Limit')[0]
        );

        $shopifyResult = new ShopifyResult(
            $response->getStatusCode(),
            $response->getReasonPhrase(),
            ((int) $totalApiCallAllowed - (int) $usedApiCall),
            \GuzzleHttp\json_decode($response->getBody()->getContents())
        );

        $guzzleClient = null;
        unset($guzzleClient);

        return $shopifyResult;
    }

    /**
     * @param string $storeName
     * @throws Exception
     */
    private function validateShopifyConfig(string $storeName): void
    {
        if (!array_key_exists($storeName, $this->shopifyConfig)) {
            throw new Exception("Invalid shopify store {$storeName}");
        }

        foreach (['baseUrl', 'username', 'password'] as $configFieldName) {
            if (!array_key_exists($configFieldName, $this->shopifyConfig[$storeName])) {
                throw new Exception("Shopify config missing {$configFieldName} for store {$storeName}");
            }
        }
    }
}


推荐阅读