Жрать не отправляя тело столба PSR-7 правильно

он либо не отправляется, либо не принимается правильно. Используя curl direct из командной строки (с использованием опции-d) или из PHP (с использованием CURLOPT_POSTFIELDS) работает.

я начинаю с запроса PSR-7:

$request = GuzzleHttpPsr7Request('POST', $url);

я добавляю заголовок аутентификации, который аутентифицируется против API правильно:

$request = $request->withHeader('Authorization', 'Bearer ' . $accessToken);

затем я добавляю тело запроса:

// The parameter for the API function
$body = GuzzleHttpPsr7stream_for('args=dot');
$request = $request->withBody($body);

я могу отправить сообщение в API:

$client = new GuzzleHttpClient();
$response = $client->send($request, ['timeout' => 2]);

ответ, который я получаю, указывает, что параметр" args " просто не был замечен API. Я попытался переместить токен аутентификации в args:

'args=dot&access_token=123456789'

это должно работать, и тут работа с curl из командной строки (-d access_token=123456789), но API не видит этот параметр также при отправке CIA curl (6.x) как указано выше.

Я вижу тут содержать тело:

var_dump((string)$request->getBody());
// string(8) "args=dot"
// The "=" is NOT URL-encoded in any way.

так что здесь может быть не так? Параметры не отправляются, или они отправляются в неправильном формате (возможно, ' = ' кодируется?), или, возможно, используется неправильный тип контента? Трудно увидеть, что отправляется "по проводу" при использовании Guzzle, так как HTTP-сообщение отформатировано и отправлено много слоев глубоко.

Edit: вызов локальный тестовый скрипт вместо удаленного API, я получаю необработанное сообщение деталь:

POST
CONNECTION: close
CONTENT-LENGTH: 62
HOST: acadweb.co.uk
USER-AGENT: GuzzleHttp/6.1.1 curl/7.19.7 PHP/5.5.9

args=dot&access_token=5e09d638965288937dfa0ca36366c9f8a44d4f3e

так это похоже на тело is отправляется, поэтому я думаю, что чего-то еще не хватает, чтобы рассказать удаленному API, как интерпретировать это тело.

Edit: завиток командной строки, который работает, отправленный в тот же тестовый скрипт, дает мне два дополнительных поля заголовка в запросе:

CONTENT-TYPE: application/x-www-form-urlencoded
ACCEPT: */*

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

2 ответов


на GuzzleHttp\Client обеспечивает всю необходимую упаковку.

$response = $client->post(
    $uri,
    [
        'auth' => [null, 'Bearer ' . $token],
        'form_params' => $parameters,
]);

документация Варианты Запроса Жрать

Edit: однако, если ваши запросы используются в GuzzleHttp\Pool, то вы можете просто все в следующее:

$request = new GuzzleHttp\Psr7\Request(
    'POST',
    $uri,
    [
       'Authorization' => 'Bearer ' . $token,
       'Content-Type' => 'application/x-www-form-urlencoded'

    ],
    http_build_query($form_params, null, '&')
);

The Content-Type заголовок был вопрос. Обычно, Guzzle будет держать вашу руку и вставлять заголовки, которые он считает необходимыми, и делает хорошее предположение о Content-Type на основе того, что вы дали ему, и как вы дали ему.

С сообщениями PSR-7 Guzzle, ни одна из этих рук не делается. Он строго оставляет все заголовки для вас. Поэтому при добавлении параметров POST в PSR-7 Request, вы должны явно установить Тип Контента:

$params = ['Foo' => 'Bar'];
$body = new \GuzzleHttp\Psr7\stream_for(http_build_query($params));
$request = $request->withBody($body);
$request = $request->withHeader('Content-Type', 'application/x-www-form-urlencoded');

возможность проходить в парамах как массив и оставлять жратву, чтобы отработать остальное, не относится к реализации PSR-7 жадности. Это немного неуклюже, так как вам нужно сериализовать параметры POST в строку HTTP-запроса, а затем вставить это в поток, но там у вас есть это. Возможно, есть более простой способ справиться с этим (например, класс-оболочка, о котором я не знаю), и я подожду и посмотрю, появится ли какой-либо из них, прежде чем принять этот ответ.

будет также известно, что при построении multipart/form-data сообщение запроса, вам нужно добавить граничную строку в тип контента:

$request = $request->withHeader('Content-Type', 'multipart/form-data; boundary=' . $boundary);

здесь $boundary может быть что-то вроде uniq() и использовано в конструкции multipart тело.