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"
);