Ошибка Laravel Guzzle — cURL 3: (см. https://curl.haxx.se/libcurl/c/libcurl-errors.html )

#php #laravel #guzzle

#php #laravel #guzzle

Вопрос:

Я создал простую оболочку вокруг REST api Shopify (частное приложение, использующее базовую аутентификацию), подобную этой, используя Guzzle:

 <?php

namespace AppServices;

use stdClass;
use Exception;
use GuzzleHttpClient as GuzzleClient;

/**
 * Class ShopifyService
 * @package AppServices
 */
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 GuzzleHttpExceptionGuzzleException
     * @throws Exception
     */
    public function Get(string $uri): stdClass
    {
        $this->checkIfGuzzleClientInitiated();;
        $result = $this->guzzleClient->request('GET', $uri);
        return GuzzleHttpjson_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 ConstantsSystem;

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(AppServicesShopifyService::class);

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

Я получаю следующую ошибку:

Ошибка 3 cURL GuzzleHttp Exception RequestException: (см. https://curl.haxx.se/libcurl/c/libcurl-errors.html )

Как вы можете видеть, я создаю простой http-клиент guzzle с опцией по умолчанию (для базового uri basic auth) и делаю последующий запрос GET.

Теоретически это должно работать, но я не могу понять, почему он выдает эту ошибку?

Я уже проверил правильность конфигурации (т. Е. Она Имеет ожидаемые значения) и попытался также очистить весь кеш laravel.

Есть идеи, что здесь может быть не так?

Комментарии:

1. Константы определяются следующим образом: <?php namespace Constants; class System { const STORE_RETAIL = 'Retail'; const STORE_TRADE = 'Trade';

Ответ №1:

По какой-то причине я не смог получить base_url опцию для работы GuzzleClient , поэтому решил ее по-другому:

 <?php

namespace AppServices;

use Exception;
use AppDTOsShopifyResult;
use GuzzleHttpClient as GuzzleClient;
use GuzzleHttpExceptionGuzzleException;

/**
 * Class ShopifyService
 * @package AppServices
 */
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),
            GuzzleHttpjson_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}");
            }
        }
    }
}