Жрать не отправляя тело столба 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 тело.