RSS Pipesを使ってURLのリダイレクトをたどったRSSを生成する

  • 投稿日:
  • by

RSS Pipesを使って、実用的なことをしよう、というお話です。

以前、RSS Pipesで広告エントリの除去という記事を書いたのですが、あまり自分でも使っていませんでした。今回、どうしてもやりたいことがあったので、久しぶりにRSS Pipesをいじりました。

やりたいことというのは、RSSのURLの修正です。RSSのURLにリダイレクトURLが使われていることがあります。例えば、bit.lyなどの短縮URLが使われている場合です。通常は困らないのですが、そのRSSをプログラムで処理しようとする場合に、短縮URLではなく最終的なURLが欲しい場合があります。めずらしいケースだとは思います。

URLのリダイレクトをたどるにはこれまでのRSS Pipesの仕組みの上だけではできず、新たな関数を作り込む必要がありました。具体的には、getRedirectURL()という関数を作りました。

ところが、このgetRedirectURL()は同期的には結果を返すことができません。nodeでは、通常callbackを使って非同期処理を書くのですが、RSS Pipesのフィルターは同期的に書くように作られていたので困りました。仕方なく、promiseを使うことにしました。

フィルターの方でもpromiseを扱えるようにする必要があるため、Qを使えるようにしました。しかし、これでブロックするようなコードも書けてしまうので、悪意コード対策がいずれ必要になりますね。promiseにタイムアウトの概念を持ち込めれば簡単にできるかしら。

さて、新しくなったRSS Pipesで書いたフィルターがこちらです。

function rssPipesFilterFunction(articles) {
  var promises = [];
  articles.forEach(function(article) {
    var maxRedirects = 5;
    var loop = function() {
      var promise = getRedirectURL(article.link).then(function(link) {
        if (article.link === link || --maxRedirects < 0) {
          return article;
        } else {
          article.link = link;
          return loop();
        }
      });
      return promise;
    };
    promises.push(loop());
  });
  return Q.all(promises);
}

https://gist.github.com/dai-shi/8934864

にも同じものを同じものを置いてあります。

リダイレクトが多重になっている場合を想定してループにしてみましたが、promiseをちゃんと理解していればもっとうまく書けるのかもしれません。どなたか改良してくれたら、うれしいです。

しかしこれでサーバ側の処理がますます重くなるので、キャッシュ機構を入れる必要がでてきそうです。そのうち、気が向いたらやりますか。今のところ、それほどユーザがいないのでほっておいても大丈夫です。それはそれでさびしいものの。