Hoxyでアセットプロキシサーバを立てる

August 6, 2016

webフロント開発で辛いことといえば、ローカルに開発環境を整えることです。

と言っても、jsのビルドがー、とかsassのビルドがー、とかそういった類の話ではありません。 そんなものはgulpなりwebpackなりでいくらでも解決できます。

何が辛いって、良い感じのAPIレスポンスを返してくれるAPIサーバを立てることです。

rails & MySQLがあれば動くようなシンプルな構成であれば問題にはなりません。 しかし、裏側で各種Cloud Serviceを使っている場合はそもそもローカルに同じ環境を用意すること自体が困難です。

また、データを更新するのに非同期ワーカーが必要だとすると、非同期ワーカーの動作環境も作らなければいけません。

ただAPIレスポンスが返って来れば良いだけなのに。。。

だがちょっと待ってください。

ローカルにそもそも全て用意する必要はあるでしょうか?

一通り動作するサーバサイドの環境はstaging環境に用意されています。 (そういう現場でなかった場合はこの記事を読む必要はありません。) 各種Cloud Serviceもstaging用に用意され、非同期処理のためのワーカーも動いています。 良い感じのデータが返ってくるテストアカウントもあります。

自分がやりたいことは、js/cssの実装です。 gulpでビルドする環境も整っています。

staging環境のサーバサイドを利用しつつ、js/cssだけはローカルのビルド結果に差し替えてしまえば良くないですか?

Hoxy

Hoxyというnode.js製のproxyサーバを使ってやってみましょう。

証明書の準備

APIエンドポイントがhttpsの場合、proxyサーバからリクエストの中身を見ることはできません。 しかし、特定リソースの取得先をローカルに向けるには、中身を見る必要があります。

proxyサーバ自体を自己証明によるhttpsサーバにすることで解決できます。 詳しいことはこちらで説明されています。

http://greim.github.io/hoxy/#direct-https-proxying

要するに、httpsの通信を一旦proxyで平文に戻し、proxyから出るときに再びまた暗号文にしているのです。

証明書の作り方などは、http://greim.github.io/hoxy/#intercept-https を参考にしてください。

証明書を作ったら、信頼する証明書としてインストールしておきましょう。 インストールしないとブラウザで警告がでます。 またHSTSが有効だと、信頼できない証明書を例外扱いにすることもできません。 (chromeでそうだった)

サーバの立ち上げ

gulpの場合は以下のタスクを定義します。

各種パス、ドメイン名などは適宜変えてください。 ここでは /assets/bundle-digest.js をローカルのファイルに差し替えるとします。

gulp.task('proxy', () => {
  const proxy = hoxy.createServer({
    certAuthority: {
      key: fs.readFileSync('/path/to/秘密鍵'),
      cert: fs.readFileSync('/path/to/自己証明書'),
    },
  }).listen(8888);

  proxy.intercept({
    phase: 'request',
    hostname: 'staging環境のドメイン',
  }, (req, resp, cycle) => {
    if(req.url.match(/bundle.*js/)) {
      cycle.serve('/path/to/ローカルでビルドしたファイル'); 
    }
  });
});

ローカルのrailsサーバ等から動的に生成したリソースを返す場合は、interceptのコールバック内を以下のようにします。 railsサーバがlocalhost:3000で動いているとすると、

(req) => {
  req.fullUrl('http://localhost:3000/assets/bundle.js');
}

となります。

gulp proxy

localhost:8888にプロキシサーバが立ち上がります。ブラウザのプロキシに設定しましょう。 http/httpsの両方に設定してください。

https://staging環境のドメイン/ にアクセスしてみましょう。 scriptタグのsrcに指定された /assets/bundle-12345.js へのリクエストが実行されますが、中身はローカルのリソースに置き換わっています。

comments powered by Disqus