要么没有被发送,要么没有被正确接收。直接从命令行(使用-d选项)或PHP(使用CURLOPT_POSTFIELDS)使用curl
确实有效。
我从PSR-7请求开始:
$request = GuzzleHttp\Psr7\Request('POST', $url);
我添加了身份验证标头,它正确地对API进行身份验证:
$request = $request->withHeader('Authorization', 'Bearer ' . $accessToken);
然后我添加请求正文:
// The parameter for the API function
$body = \GuzzleHttp\Psr7\stream_for('args=dot');
$request = $request->withBody($body);
我可以将消息发送到API:
$client = new \GuzzleHttp\Client();
$response = $client->send($request, ['timeout' => 2]);
我回复的回应表明" args"参数根本没有被API看到。我已经尝试将身份验证令牌移动到args:
'args=dot&access_token=123456789'
这应该可行,并且从命令行(-d access_token=123456789
)使用curl工作但是在发送cia curl(6.x)时API也无法看到该参数
我可以看到消息 包含正文:
var_dump((string)$request->getBody());
// string(8) "args=dot"
// The "=" is NOT URL-encoded in any way.
那么这里可能出现什么问题?参数是否未被发送,或者是否以错误的格式发送(可能' ='正在编码?),或者可能是使用的内容类型错误?很难看到正在发送的内容和#34;使用Guzzle时,因为HTTP消息被格式化并发送了很多层。
编辑:调用local test script而不是远程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
所以看起来身体是正在发送,所以我想还有其他东西缺少告诉远程API如何解释那个身体。
编辑:发送到同一测试脚本的命令行curl工作,在请求中给了我两个额外的头字段:
CONTENT-TYPE: application/x-www-form-urlencoded
ACCEPT: */*
我猜它是Guzzle请求中缺少的内容类型标头,这是问题的根源。这是一个Guzzle bug吗?是不是总是发送内容类型,基于它所做的假设是listed in the documentation?
答案 0 :(得分:13)
Content-Type
标题就是问题所在。通常情况下,Guzzle会抓住你的手并插入它认为必要的标题,并根据你提供的内容和{em>你给你的来猜测Content-Type
。
使用Guzzle的PSR-7消息,没有完成任何手持操作。它严格保留所有标题供您处理。因此,在将POST参数添加到PSR-7 Request
时,您必须明确设置Content-Type:
$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');
能够将params作为数组传递并让Guzzle完成剩下的工作,这不适用于Guzzle的PSR-7实现。它有点笨拙,因为你需要将POST参数序列化为HTTP查询字符串,然后将其粘贴到流中,但是你有它。可能有一种更简单的方法来处理这个问题(例如我不知道的包装类),在接受这个答案之前我会等着看是否有任何问题。
还要注意,如果构造multipart/form-data
请求消息,则需要将边界字符串添加到Content-Type:
$request = $request->withHeader('Content-Type', 'multipart/form-data; boundary=' . $boundary);
$boundary
可以是类似uniq()
的内容,用于构建多部分正文。
答案 1 :(得分:7)
GuzzleHttp\Client
提供了所有必要的包装。
$response = $client->post(
$uri,
[
'auth' => [null, 'Bearer ' . $token],
'form_params' => $parameters,
]);
编辑:但是,如果您的请求正在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, '&')
);