web-dev-qa-db-ja.com

ガズルがPSR-7を送信しないPOST本文が正しく送信されない

送信されていないか、正しく受信されていません。コマンドラインから直接(-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'

これは機能するはずであり、doesはコマンドラインからのcurlで機能します(-d access_token=123456789)ただし、上記のようにcia curl(6.x)を送信する場合も、APIはそのパラメーターを認識できません。

メッセージdoesに本文が含まれていることがわかります:

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

では、ここで何がうまくいかないのでしょうか?パラメータが送信されていないのですか、それとも間違った形式で送信されているのですか(おそらく、「=」がエンコードされていますか?)、または間違ったコンテンツタイプが使用されていますか? HTTPメッセージはフォーマットされ、多くのレイヤーの深さで送信されるため、Guzzleを使用する場合、「ネットワーク上」で何が送信されているかを確認することは困難です。

編集:リモート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にその本文を解釈する方法を指示するために何か他のものが不足していると思います。

編集:同じテストスクリプトに送信された、機能するコマンドラインcurlは、リクエストに2つの追加ヘッダーフィールドを提供します。

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

問題の原因であるのは、Guzzleリクエストから欠落しているcontent-typeヘッダーであると推測します。それで、これはガズルのバグですか? ドキュメントに記載されている であるという仮定に基づいて、常にContent-Typeを送信する必要はありませんか?

9
Jason

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, '&')
);
9
Shaun Bramley

_Content-Type_ヘッダーが問題でした。通常、Guzzleはあなたの手を握り、必要と思われるヘッダーを挿入し、あなたが与えたものに基づいて_Content-Type_を適切に推測し、howあなたがそれを与えました。

GuzzleのPSR-7メッセージでは、その手持ちは行われません。それはあなたが扱うために厳密にすべてのヘッダーを残します。したがって、POSTパラメータをPSR-7Requestに追加するときは、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()のようなものであり、マルチパートボディの構築に使用されます。

13
Jason