Пустое тело при POST-запросе в Guzzle6 / PSR7

#php #guzzle6

#php #guzzle6

Вопрос:

Я использую Guzzle6 в версии PSR7, потому что он хорошо интегрируется с аутентификацией Hawk. Теперь я сталкиваюсь с проблемами добавления тела к запросу.

 private function makeApiRequest(Instructor $instructor): ResponseInterface
{
    $startDate = (new CarbonImmutable('00:00:00'))->toIso8601ZuluString();
    $endDate = (new CarbonImmutable('00:00:00'))->addMonths(6)->toIso8601ZuluString();
    $instructorEmail = $instructor->getEmail();
    $body = [
        'skip' => 0,
        'limit' => 0,
        'filter' => [
            'assignedTo:user._id' => ['email' => $instructorEmail],
            'start' => ['$gte' => $startDate],
            'end' => ['$lte' => $endDate],
        ],
        'relations' => ['reasonId']
    ];

    $request = $this->messageFactory->createRequest(
        'POST',
        'https://app.absence.io/api/v2/absences',
        [
            'content_type' => 'application/json'
        ],
        json_encode($body)
    );

    $authentication = new HawkAuthentication();
    $request = $authentication->authenticate($request);

    return $this->client->sendRequest($request);
}
  

Когда я var_dump ввожу $request переменную, я не вижу тела внутри запроса. Это подтверждается тем фактом, что API отвечает так, как будто тело не было отправлено. Я перепроверил это в Postman. Как вы можете видеть, в теле указаны фильтры и разбивка на страницы, поэтому легко заметить, что результаты, которые я получаю, на самом деле не фильтруются.

Тот же запрос в Postman (с телом) работает безупречно.

Поскольку параметр может иметь тип StreamInterface , вместо этого я создал поток и передал ему тело. Тоже не сработало.

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

1. Действительно, не рекомендовал бы писать свой собственный JSON. Создайте массив и используйте json_encode() вместо

2. Да, у меня было предчувствие, что ты делаешь это не так. Спасибо за комментарий. Теперь заменено на array.

3. Все еще не работает, верно: (

4. Нет… К сожалению, нет. Пробовал это и раньше. Копаясь в реализации Guzzle, я, кажется, не могу понять, что делает stream_for(). А также не причина, по которой в RequestInterface отсутствует какой-либо метод, связанный с телом или содержимым…

Ответ №1:

Простые JSON запросы могут быть созданы без использования json_encode() … смотрите документацию.

 use GuzzleHttpClient;

$client = new Client([
    'base_uri' => 'https://app.absence.io/api/v2',
    'timeout'  => 2.0
]);

$response = $client->request('POST', '/absences', ['json' => $body]);
  

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

1. Я использую вариант PSR7, потому что он позволяет легко интегрировать аутентификацию Hawk. Ваше предложение вынудило бы меня использовать систему событий Guzzle для обогащения запроса заголовком аутентификации.

2. @Chrisissorry существует несколько способов создания запросов, поэтому я добавил термин «простой». Сначала не заметил неверный content_type заголовок, но это может быть интерпретировано не как данные формы, а, скорее всего, как text/plain (такие нераспознанные заголовки, скорее всего, будут проигнорированы).

Ответ №2:

Обнаружена проблема, на самом деле мое тело POST НЕ пустое. Просто оказывается, что сброс Request ничего не намекает на фактическое тело, вложенное в сообщение.

Я могу порекомендовать всем, у кого есть подобные проблемы, использоватьhttp://httpbin.org/#/HTTP_Methods/post_post для отладки тела POST.

Наконец, проблема заключалась в том, что мое content_type написание заголовка было неправильным, поскольку сервер ожидает заголовок Content-Type . Из-за этого данные JSON были отправлены как данные формы.