cURL POST-запрос работает, Guzzle 6 не работает

Контекст:

Я работал над выяснением того, как заставить это работать некоторое время, и я просто не понимаю, почему Guzzle не работает для этого конкретного запроса. Та же самая структура инициализации и запроса работает в некоторых базовых модульных тестах, которые у меня есть, но когда дело доходит до API для взаимодействия с API, Guzzle просто не взаимодействует.

Проблема:

Я имею в виду, что это не включает заголовки, которые я устанавливаю в $headers массив, а тело запроса пусто.

Желаемый результат:

Чтобы подтвердить, что это проблема с Guzzle, я выписал запрос с типичным синтаксисом cURL, и запрос проходит нормально. Мне просто нужно несколько советов о том, как заставить это работать с Guzzle, так как мне нравится абстракция, которую Guzzle предлагает над подробными запросами cURL.

Рабочий запрос cURL:

    $headers = array(
        'Authorization: Bearer '.$sharedSecret,
        'Content-Type: application/x-www-form-urlencoded',
        'Accept: application/json',
        'Content-Length: '.strlen($loginDetails),
    );

    $curlOptions = array(
        CURLOPT_URL             => API_URL.'member/SessionManager',
        CURLOPT_HTTPHEADER      => $headers,
        CURLOPT_RETURNTRANSFER  => FALSE,
        CURLOPT_HEADER          => FALSE,
        CURLOPT_FOLLOWLOCATION  => FALSE,
        CURLOPT_ENCODING        => "",
        CURLOPT_USERAGENT       => "PORTAL",
        CURLOPT_AUTOREFERER     => TRUE,
        CURLOPT_CONNECTTIMEOUT  => 120,
        CURLOPT_TIMEOUT         => 120,
        CURLOPT_MAXREDIRS       => 10,
        CURLOPT_POST            => TRUE,
        CURLOPT_POSTFIELDS      => $loginDetails,
        CURLOPT_SSL_VERIFYHOST  => FALSE,
        CURLOPT_SSL_VERIFYPEER  => FALSE,
        CURLOPT_VERBOSE         => FALSE
    );

    try {
        $ch = curl_init();
        curl_setopt_array($ch,$curlOptions);
        $content    = curl_exec($ch);
        $err        = curl_errno($ch);
        $errmsg     = curl_error($ch);
        $response   = curl_getinfo($ch);
        curl_close($ch);

        if ($content === FALSE) {
            throw new Exception(curl_error($ch), curl_errno($ch));
        } else {
            return true;
        }
    } catch(Exception $e) {
        trigger_error(sprintf('Curl failed with error #%d: %s', $e->getCode(), $e->getMessage()), E_USER_ERROR);
    }

Клиент Guzzle инициализируется в глобальном файле, который создает контейнер, в котором хранятся различные объекты, которые мы используем в приложении. Я включаю это в случае, если я пропустил что-то жизненно важное, чего нет в документации Guzzle.

Инициализация жрет:

$container['client'] = function ($c) {
    return new \GuzzleHttp\Client([
        'base_uri'          => API_URL,
        'timeout'           => 30.0,
        'allow_redirects'   => true,
        'verify'            => false,
        'verbose'           => true,
        [
            'headers'   => [
                'Authorization' => 'Bearer '.$sharedSecret,
            ]
        ],
    ]);
};

Нерабочий запрос на жадность:

    $headers = array(
        'Authorization' => 'Bearer '.$sharedSecret,
        'Content-Type'  => 'application/x-www-form-urlencoded',
        'Accept'        => 'application/json',
        'Content-Length'=> strlen($loginDetails),
    );

    try {
        $response = $this->client->post('/api/member/SessionManager',
            ['debug'            => true],
            ['headers'          => $headers],
            ['body'             => $loginDetails]
        );

        if($response) {
            $this->handleResponse($response);
        }

    } catch (GuzzleHttp\Exception\ClientException $e) {
        $response->getResponse();
        $responseBodyAsString = $response->getBody()->getContents();
    }

Удаляю ли я headers массив в инициализации жрет или нет, не важно. Заголовок Authorization нигде не найден в запросе (подтверждается с помощью tcpdump, Wireshark и регистрации ошибок API), а выходные данные отладки Guzzle не показывают никаких указаний на мои заголовки и на то, что мое тело запроса находится где-либо в запросе.

Я озадачен тем, почему это не работает, и очень хотел бы понять. Я могу пойти по пути, не используя Guzzle, но действительно предпочел бы из-за краткости. Любой вклад будет принята с благодарностью.

1 ответ

В запросе cURL вызываемый URL API

API_URL.'member/SessionManager'

В то время как в запросе Guzzle, вызываемый URL API имеет дополнительный текст "/api/" (при условии, что API_URL определен в обоих случаях одинаково)

new \GuzzleHttp\Client([ 'base_uri' => API_URL,

...

$this->client->post('/api/member/SessionManager',

Цените, что вопрос старый, но я подумал, что поделюсь своим опытом, поскольку я тоже боролся с этим. Эквивалент:

CURLOPT_POSTFIELDS      => $loginDetails,

в Guzzle это:

"query" => $loginDetails

Кроме того, я обнаружил, что если base_uri не заканчивается /, Guzzle неправильно это поймет.

С учетом всего этого, ваш запрос POST должен быть следующим:

        $response = $this->client->post('api/member/SessionManager', // Removed the first / as it's part of the base_uri now
            ['debug'            => true],
            ['headers'          => $headers],
            ['query'            => $loginDetails] // Replaced "body" with "query"
        );
Другие вопросы по тегам