• wp_remote_get()の結果はWP_Error、HTTPステータス、本文を分けて確認する

wp_remote_get()の結果はWP_Error、HTTPステータス、本文を分けて確認する

公開日: 執筆:佐藤

wp_remote_get()の返り値は、最初にis_wp_error()で通信処理の失敗を確認します。応答を受け取れた場合は、HTTPステータスを確認し、その条件を満たしたときだけ本文を使います。

WP_Errorではないことだけを成功条件にしてはいけません。接続先が404や500を返しても応答配列を受け取る場合があり、200でも期待する形式の本文とは限りません。

通信、HTTP応答、本文は三つの段階である

WordPress 3.8のHTTP APIでは、wp_remote_get()は成功時の応答配列または失敗時のWP_Errorを返します。

段階 確認方法 分かること まだ分からないこと
通信処理 is_wp_error() WordPressが要求を完了できたか 接続先が要求を受理したか
HTTP応答 wp_remote_retrieve_response_code() 200、404、500などの状態 本文が期待するデータか
本文 wp_remote_retrieve_body()と形式検査 受け取った内容 その内容が業務上正しいか

DNS、接続、SSL、タイムアウトなどの問題は、WP_Errorとして返ることがあります。HTTPステータスは、接続先から応答が返ったあとの結果です。本文の形式と値は、さらに別の検査です。

WP_Errorを最初に確認する

固定した外部URLから情報を取得する基本形は、次のようになります。

$response = wp_remote_get(
    'https://api.example.com/status',
    array(
        'timeout' => 10,
    )
);

if ( is_wp_error( $response ) ) {
    $error_code    = $response->get_error_code();
    $error_message = $response->get_error_message();

    return;
}

WP_Errorには、エラーコードとメッセージがあります。利用者へ内部情報をそのまま表示せず、管理用の記録へ残し、公開画面では代替表示や再試行案内を出します。

wp_remote_retrieve_response_code()とwp_remote_retrieve_body()は、WP_Errorを渡すと空文字列を返します。先にエラーを分けないと、通信失敗、応答コードの欠落、空の本文を同じ空文字列として扱うことになります。

HTTPステータスを本文より先に確認する

通信処理が完了したら、HTTPステータスを取り出します。

$status = (int) wp_remote_retrieve_response_code( $response );

if ( 200 !== $status ) {
    return;
}

$body = wp_remote_retrieve_body( $response );

この例は、接続先の仕様で200だけを受理する場合です。201、204など、ほかの成功ステータスを使うサービスでは、その仕様に合わせて許可する値を決めます。

404は取得対象がないこと、500は接続先の処理失敗を示しますが、どちらもWordPress側の通信機能が失敗したという意味ではありません。is_wp_error()だけで分岐すると、エラーページのHTMLを正しいデータとして保存する危険があります。

反対に、404や500の本文には診断用の情報が入る場合があります。業務データとしては使わず、必要な範囲だけ管理記録へ残します。認証情報、個人情報、接続先が返した全文を無条件にログへ書かないでください。

200でも本文の形式を確認する

HTTP 200は、要求に対して成功応答が返ったことを示します。本文が空でないこと、期待する形式であること、必要な項目があることまでは保証しません。

接続先ごとに、次の条件を決めます。

  • 受理するHTTPステータス
  • 空の本文を許すか
  • HTML、XML、JSONなど期待する形式
  • 必須項目と値の範囲
  • データが不完全な場合の代替表示
  • 再試行する条件と回数

説明用の仮例では、在庫APIから200とHTMLのメンテナンス画面が返ることがあります。HTTP上の成功だけで、そのHTMLを在庫データとして保存してはいけません。形式と必須項目を確認し、失敗した取得結果で保存済みデータを上書きしない判断が必要です。

本文を公開画面へ出す場合も、接続先を信用してそのままHTMLとして出力しません。用途に応じてデータを検証し、文字列なら適切にエスケープします。

利用者が指定するURLにはwp_safe_remote_get()を検討する

取得先がテーマやプラグインで固定され、管理者が確認したURLなら、wp_remote_get()で要求できます。一方、フォームや外部データから任意のURLを受け取る場合は、内部ネットワークへの要求や危険なリダイレクトを防ぐ必要があります。

WordPress 3.8のwp_safe_remote_get()は、reject_unsafe_urlsを有効にして要求します。利用者が指定できるURLでは、この関数を検討し、許可するスキーム、ホスト、用途も別に制限します。

安全用の関数を使っても、取得した本文が正しい業務データになるわけではありません。URLの安全確認と、HTTPステータス、本文の検証は別々に行います。

失敗記録は段階を残す

外部取得を保守するときは、「APIエラー」と一語で記録せず、失敗した段階を残します。

記録項目 例
取得先 認証情報を除いたホストとパス
通信結果 WP_Errorのコード、必要な範囲のメッセージ
HTTP結果 ステータスコード
本文検査 空、形式違い、必須項目なしなど
処理判断 既存データ維持、代替表示、再試行
管理情報 実行日時、担当、設定変更の有無

制作会社へ実装を委託しても、取得先、認証情報の管理者、失敗時に残すデータ、再試行条件はサイト側で決めます。接続先の障害で、自社サイトの公開画面や保存済みデータまで壊さない構成にします。

最初の一手は、既存のwp_remote_get()を一つ選び、is_wp_error()、HTTPステータス、本文検査の三段階があるかを確認することです。どれか一つしかなければ、保存や表示より前に分岐を追加してください。

戻る