Guzzle で API を叩いていたのですが、レスポンスのステータスコードが 200 なのにボディ部が []
(空配列) だったので嵌まってしまいました。そこで検証のため、ブラウザから POST しようとした、というお話です。
検証のため、以下のようなリクエストヘッダとレスポンスヘッダを出力するだけの PHP を用意します。
<?php
date_default_timezone_set('Asia/Tokyo');
mb_language('ja');
mb_internal_encoding('UTF-8');
$status = [
'code' => 200,
'message' => 'OK.',
];
// request
$requestHeaders = apache_request_headers();
unset($requestHeaders['Cookie']);
$requestHeaders['Method'] = $_SERVER['REQUEST_METHOD'];
$requestBodies = file_get_contents('php://input');
$request = [
'headers' => $requestHeaders,
'bodies' => $requestBodies,
];
switch ($_SERVER['REQUEST_METHOD']) {
case 'GET':
$status['code'] = 200;
$status['message'] = 'OK.';
break;
case 'POST':
$status['code'] = 200;
$status['message'] = 'OK.';
break;
case 'PUT':
$status['code'] = 201;
$status['message'] = 'Created.';
break;
case 'DELETE':
$status['code'] = 205;
$status['message'] = 'Reset Content.';
break;
case 'HEAD':
$status['code'] = 400;
$status['message'] = 'Bad Request.';
break;
case 'OPTIONS':
$status['code'] = 405;
$status['message'] = 'Method Not Allowed.';
break;
case 'PATCH':
$status['code'] = 409;
$status['message'] = 'Conflict.';
break;
default:
$status['code'] = 405;
$status['message'] = 'Method Not Allowed.';
break;
}
// response
$responseHeaders = [
'Code' => $status['code'],
'Status-Message' => $status['message'],
'Protocol' => $_SERVER['SERVER_PROTOCOL'],
'Host' => $_SERVER['HTTP_HOST'],
'Date' => date('D, d M Y H:i:s T'),
'Connection' => isset($_SERVER['HTTP_CONNECTION']) && !empty($_SERVER['HTTP_CONNECTION']) ? $_SERVER['HTTP_CONNECTION'] : 'Close',
'X-Powered-By' => explode(' ', $_SERVER['SERVER_SOFTWARE'])[0] . '/' . explode(' ', $_SERVER['SERVER_SOFTWARE'])[1],
'Content-Type' => isset($_SERVER['CONTENT_TYPE']) && !empty($_SERVER['CONTENT_TYPE']) ? $_SERVER['CONTENT_TYPE'] : '',
];
$responseBodies = file_get_contents('php://input');
$response = [
'headers' => $responseHeaders,
'bodies' => $responseBodies,
];
// concat
$output = json_encode(
[
'request' => $request,
'response' => $response
],
JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP | JSON_UNESCAPED_UNICODE
);
// output
header('Content-Type: application/json; charset=UTF-8');
header($_SERVER['SERVER_PROTOCOL'] . ' ' . (string)$status['code'] . ' ' . $status['message']);
echo $output;
次に、 Chrome拡張機能 の Talend API Tester をインストールします。
そして、先程の PHP が置いてある Webサーバ に向けて各メソッドとデータの投げ込みを試します。
確かに POST や他のメソッドがリクエストできていることが確認できました。
ここで、 Guzzle で上手く行っていない API に向けて POST したところ、正常なレスポンス、ボディ部もきちんと JSON が返却されていることが確認できました。
この Chrome拡張機能、自作の API の動作確認するとき等で役に立ちそうですね。
さて、本題の Guzzle がコケていた原因ですが……結局はレスポンスのデータを格納している Guzzle のオブジェクトから取り出す方法を間違えていただけでした (処理自体は正しく完了していた)。
具体的には、 Guzzle のレスポンス $rensponse
に対し、 $response->getBody()
ではダメで、 $response->getBody()->getContents()
までしないとレスポンスボディ部の JSONデータ が拾えなかった、というオチ。
なお、今回のケースでは $response->getBody()->getContents()
の出力が文字列なのでそのまま echo
しても良い状態でした。
あるいは、冗長ですが json_encode(json_decode($response->getBody(), true), JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP | JSON_UNESCAPED_UNICODE)
と一度 JSON をデコードしてオブジェクトの形で取り出してから、再度 JSON エンコードで JSON文字列 にすれば上述と同様の結果が出力されました。
headers
は \GuzzleHttp\RequestOptions::HEADERS
、form_params
は \GuzzleHttp\RequestOptions::FORM_PARAMS
で指定できるCrieitは誰でも投稿できるサービスです。 是非記事の投稿をお願いします。どんな軽い内容でも投稿できます。
また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!
こじんまりと作業ログやメモ、進捗を書き残しておきたい方はボード機能をご利用ください。
ボードとは?
コメント