プロキシサーバを作りたい

Web 開発を行っていて、僕の環境だけ LiveReload が期待通りに機能せず、500 エラーが頻発するという現象に見舞われた。

原因は LiveReload で、HTML から LiveReload 関連の script タグをいくつか取り除くだけでエラーが出なくなるので、ソースツリーには手を加えずに script タグを取り除く、ということをしたい。

試したのは Chrome Extension で取り除く方法。

これは:

chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
  if (tab.url.startsWith("http://ubuntu:8080/")) {
    chrome.tabs.sendMessage(tab.id, {
      command: "remove_livereload"
    },
    function(msg) {
      if (msg !== undefined) {
        alert(msg);
      }
    });
  }
});

のような感じでコールバックを仕込んで:

chrome.runtime.onMessage.addListener(function(msg, sender, sendResponse) {
  if (msg.command === "remove_livereload") {
    $("script").each(function(index, element) {
      if ($(element).attr("type") === "text/javascript") {
        if ($(element).text().indexOf('WEB_SOCKET_SWF_LOCATION = "/__rack/WebSocketMain.swf";') !== -1 ||
            $(element).attr("src") === "/__rack/swfobject.js" ||
            $(element).attr("src") === "/__rack/web_socket.js" ||
            $(element).text().indexOf("RACK_LIVERELOAD_PORT = 35729;") !== -1 ||
            $(element).attr("src") === "/__rack/livereload.js?host=0.0.0.0&port=35729") {
          $(element).remove();
        }
      }
    });
  }
});

のような感じで DOM 操作することで、目的の script タグを除去することができる。


ただし、chrome.tabs.onUpdated.addListener というコールバック名からも分かる通り、HTML をパースして DOM ツリーが完成した後で呼び出されるので、このタイミングだと JavaScript は動いてしまっている。

Chrome API リファレンスをくまなく見てみたところ、以下のイベントコールバックを見つけた。

chrome.webNavigation.onDOMContentLoaded.addListener

これは DOM をパースし終えて、まだ JS の処理を行う前に呼び出されるコールバックなんだけど、このコールバックで通知されるのは、JS がアクセスしようとしている URL だったりして、またちょっと目的を果たせない。

このコールバックでちょっと遊んでみたんだけど、世の中は広告だらけだなぁ、と改めて実感した。Chrome で新規タブを開くだけで、ChromeGoogle の広告サーバにアクセスしてるのがわかった。

さて、Chrome Extension の仕様として、コールバック内で DOM 操作などは行えず、サンプルのように sendMessage でメッセージを送り、onMessage コールバック内で行う必要がある。つまり非同期なので、いくら最適なタイミングでコールバックが呼び出されたとしても、実際の処理を行うタイミングで処理が進んでしまっているので、JS が行う通信を完全に防ぐことは Chrome Extension ではできない。


もしかしたら Firefox なら出来るのかもしれないけど、ブラウザ拡張でどうにかするのは諦めて、プロキシサーバを立てて見ようと思う。Nginx が簡単そうだけど、Haskell で汎用的に作りたいような気分。