FeedlyのDDoS攻撃被害から学ぶwp_remote_get()エラー処理の重要性

feedlyロゴ

※当ブログではアフィリエイト広告を利用しています。

当サイトではFeedlyの購読者数をAPIから取得し、エントリ下部のソーシャルボックス一覧部分で表示しています。しかし2014/06/11にFeedlyがDDoS攻撃を受けたことに伴い、該当部分とブログのサイドバーのレイアウトが崩れる可能性があることがわかりました。

FeedlyのAPIはwp_remote_get()関数で実行・結果を取得しており、そのエラー処理が重要だと感じたので購読者数取得処理を修正した内容をメモします。

2014/06/11のFeedlyへのDDoS攻撃について

2014/06/11現在Feedlyが何者かからDDoS攻撃(分散型サービス停止攻撃)を受けており、同サービスに接続しづらい状況が続いています。

公式サイトでは犯人より、攻撃を停止するために金銭を要求されている旨がアナウンスされていますが、Feedly側は屈することなく対応中とのことです。

Denial of service attack

2:04am PST – Criminals are attacking feedly with a distributed denial of service attack (DDoS). The attacker is trying to extort us money to make it stop. We refused to give in and are working with our network providers to mitigate the attack as best as we can.

引用元:Denial of service attack | Building Feedly

Feedlyに繋がりにくくなることによるサイトへの影響

当サイトではエントリの下部に、Feedly購読者数をバルーン形式で表示しています。下の画像のようなものです。

Feedly購読者数

バルーン設置にあたっては下記サイト様を参考にしました。WordPressに設置するためのコードも全て載っています。

参考サイト:[M]RSSの登録に便利!購読者数付きのバルーンなFeedlyボタンをシェアボタンと一緒に設置してみた | miMemo(ミメモ)

該当の箇所では以下の流れでFeedlyの購読者数を取得しています。

  1. WordPressのDBにFeedly購読者数が一時保存されていなかったらwp_remote_get()関数でFeedlyのAPIから購読者数を取得する
  2. 取得した購読者数をWordPressのDBに一時保存する(12時間)
  3. 12時間後に一時保存された購読者数がWordPressのDBから消えるので1に戻る

が、今回Feedlyに繋がりにくくなったことによりWordPressのwp_remote_get()関数でFeedly購読者数を取得している部分で、ブログ表示の処理が途中で止まってしまう可能性があることがわかりました。該当部分のコードは以下の通りです。

if ( false === ( $subscribers = get_transient( 'feedly_subscribers' ) ) ) :
    $feed_url = rawurlencode( get_bloginfo( 'rss2_url' ) );

    //ここでFeedlyに繋がらないと以降の処理がエラーに
    $subscribers = wp_remote_get( "http://cloud.feedly.com/v3/feeds/feed%2F$feed_url" );
    $subscribers = json_decode( $subscribers['body'] );
    $subscribers = $subscribers->subscribers;
  
    set_transient( 'feedly_subscribers', $subscribers, 60 * 60 * 12 );
endif;

上記コードのwp_remote_get()の部分でFeedlyのAPIのURLを叩いて取得した結果を変数に入れようとしていますが、Feedlyに繋がらない状態だとそれ以降の処理が正常に動作しません。

ためしにローカルのテスト環境でやってみたところ、個別記事画面でソーシャルボタンから下の部分とサイドバーが表示されなくなってしまいました。

wp_remote_get()関数にエラー処理を加える

上記はFeedlyから購読者数を取得するときのエラー処理を考慮していないものだったため、is_wp_error()関数を使いwp_remote_get()関数の結果にエラーが無いか調べるように変更しました。ついでに多少コードが見やすくなるよう修正しました。変更後のコードは以下の通りです。

//Transient名称(DBに一時的に保存するFeedlyの購読者数)
$transientname = "feedly_subscribers";

//Feedly購読者数がDB保存されていないか期限切れの場合、APIから取得する
if ( false === ( $subscribers = get_transient( $transientname ) ) ) :
    $feed_url = rawurlencode( get_bloginfo( 'rss2_url' ) );
 
    $response = wp_remote_get("http://cloud.feedly.com/v3/feeds/feed%2F$feed_url");

    if( !is_wp_error( $response ) ) {
        //エラーが無い場合購読者数をDB保存する
        $subscribersbody = json_decode( $response['body'] );
        $subscribers = $subscribersbody->subscribers;
        //DB保存の有効期限は12時間とする
        set_transient( $transientname, $subscribers, 60 * 60 * 12 );
    }
    else{
        //購読者数取得でエラーとなった場合、購読者数を一時的に?とする
        $subscribers = "?";
        //DB保存の有効期限は1時間とする
        set_transient( $transientname, $subscribers, 60 * 60 * 1 );
    }
    
endif;

上記のコードではFeedlyから購読者数を取得できなかった場合、購読者数をひとまず?とし、set_transient()関数で1時間だけWodrdPressのDBに一時保存します。1時間後に一時保存した値がDB消えるため、その次にアクセスがあった時に再度Feedly購読者数の取得をトライします。

他にスマートなやり方があるかもしれませんが、ひとまずこの方法でFeedlyに繋がらない時もブログ表示が崩れるのは回避できそうです。

おわりに

基本的なことですがエラーがあったときの処理を忘れているという凡ミスでした。

他所で参考にさせて頂いたコードをWordPressに組み込むときはそのまま組み込むのではなく、内容をある程度理解した上で必要な処理を加える等して使うのが重要だと感じました。