枪口未正确发送PSR-7 POST正文 [英] Guzzle not sending PSR-7 POST body correctly
问题描述
它没有被发送,或者没有被正确接收.直接从命令行(使用-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]);
我得到的响应表明API根本看不到"args"参数.我尝试将身份验证令牌移至args:
'args=dot&access_token=123456789'
这应该可以工作,并且可以从命令行(-d access_token=123456789
)使用curl,但是在如上所述发送cia curl(6.x)时,API也无法看到该参数. /p>
我可以看到消息确实包含正文:
var_dump((string)$request->getBody());
// string(8) "args=dot"
// The "=" is NOT URL-encoded in any way.
那么这里可能出什么问题了?是不是发送了参数,还是以错误的格式发送了参数(也许正在编码'='?),或者是否使用了错误的内容类型?在使用Guzzle时,很难看到正在在线"发送的内容,因为HTTP消息已格式化并发送了很多层.
调用本地测试脚本而不是远程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请求中缺少的内容类型标头,这是问题的根源.那这是一个食尸鬼的错误吗?如果它不总是发送Content-Type,则基于以下假设:文档?
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, '&')
);
It is either not being sent, or not being received correctly. Using curl
direct from the command line (using the -d option) or from PHP (using CURLOPT_POSTFIELDS) does work.
I start with a PSR-7 request:
$request = GuzzleHttp\Psr7\Request('POST', $url);
I add authentication header, which authenticates against the API correctly:
$request = $request->withHeader('Authorization', 'Bearer ' . $accessToken);
Then I add the request body:
// The parameter for the API function
$body = \GuzzleHttp\Psr7\stream_for('args=dot');
$request = $request->withBody($body);
I can send the message to the API:
$client = new \GuzzleHttp\Client();
$response = $client->send($request, ['timeout' => 2]);
The response I get back indicates that the "args" parameter was simply not seen by the API. I have tried moving the authentication token to the args:
'args=dot&access_token=123456789'
This should work, and does work with curl from the command line (-d access_token=123456789
) but the API fails to see that parameter also when sending cia curl (6.x) as above.
I can see the message does contain the body:
var_dump((string)$request->getBody());
// string(8) "args=dot"
// The "=" is NOT URL-encoded in any way.
So what could be going wrong here? Are the parameters not being sent, or are they being sent in the wrong format (maybe '=' is being encoded?), or is perhaps the wrong content-type being used? It is difficult to see what is being sent "on the wire" when using Guzzle, since the HTTP message is formatted and sent many layer deep.
Edit: Calling up a local test script instead of the remote API, I get this raw message detail:
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
So it looks like the body is being sent, so I guess something else is missing to tell the remote API how to interpret that body.
Edit: the command-line curl that does work, sent to the same test script, gives me two additional header fields in the request:
CONTENT-TYPE: application/x-www-form-urlencoded
ACCEPT: */*
I'm going to guess it is the content-type header which is missing from the Guzzle request which is the source of the problem. So is this a Guzzle bug? Should it not always sent a Content-Type, based on the assumptions it makes that are listed in the documentation?
The GuzzleHttp\Client
provides all necessary wrapping.
$response = $client->post(
$uri,
[
'auth' => [null, 'Bearer ' . $token],
'form_params' => $parameters,
]);
Documentation available Guzzle Request Options
Edit: However, if your requests are being used within GuzzleHttp\Pool then, you can simply everything into the following:
$request = new GuzzleHttp\Psr7\Request(
'POST',
$uri,
[
'Authorization' => 'Bearer ' . $token,
'Content-Type' => 'application/x-www-form-urlencoded'
],
http_build_query($form_params, null, '&')
);
这篇关于枪口未正确发送PSR-7 POST正文的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!