Plack::App::Proxy::Selectiveとか作ってみた
マクラ
どうも、大してPerlも書けないのに会社のローカルでは常に3つほどplackupでサーバ立ち上げて作業しているzentoooです。すいませんすいません。
企業で働いていると、関与してはいるけれど自分には権限がないので本番サーバあるいはそれに準ずるサーバにアップできないファイルに、よく遭遇しますよね。
そういった事態にあまり遭遇しない場合でも、本番サーバにアップする前に、本番環境で現在編集中のcssやらjsやらのファイルをテストしたい、テストできたらいいなあ、という需要はけっこうあったりなかったりするんではないでしょうか。
んで、僕の場合もそういったことがちょいちょいあったりするわけです。本番環境って、直にユーザにつながっているものなので権限があろうとなかろうと気軽にファイルをアップできるものではありません。
というようなことを考えたり考えなかったりしていると、id:ZIGOROuさんに「それHTTP::Proxy::Selectiveでできるよ!」と以下のページを教えてもらい、しばらくselective_proxyを使っていました。
http://tech.kayac.com/archive/local-proxy-by-perl-and-pac.html
HTTP::Proxy::Selectiveはこちら(CPAN)
http://search.cpan.org/dist/HTTP-Proxy-Selective/lib/HTTP/Proxy/Selective.pm
一つ目のリンク先に書いてあるとおり、ちょっとした設定ファイルを書き換えるだけでリモートのサーバの特定のパスに置いてある静的ファイルをローカルのファイルに読み替えることができ、「おお、これ便利やんけ!」ってな感じにコーフンしておりました。
で、しばらく使っているうちにいくつか問題点が…
HTTP::Proxy::Selectiveの問題点というか気になる点
- なぜかすぐ死んでしまう
そんなに検証しなかったのでどういう状況下で起こるのかはよく分かっていませんが、なぜか特定の状況下でローカルに立ててるプロキシサーバが何の断りもなく(スタックトレース等もなく)死んでしまうという致命的な問題点
- 設定ファイルが.ini
一風変わったOSを使っている人以外にとっては馴染みの薄い形式
- 設定に融通がきかない
なんでHTTP::Proxy::Selectiveすぐ死んでしまうん?
実は一番上の問題点以外は割とどうでもよかったりするのですが、特定の状況下でなぜか死ぬ、というのがなかなか面倒で、特に僕の場合は「本番サーバでは死なないが、本番の一段階前のサーバに使うと死ぬ」という「むしろ逆にしてくれよ!」みたいななんだかとても微妙な動作状況。
「すぐ死んでしまうホタルみたいなモジュールを直してられっかバッキャロウ!」ということで、「それPlackで(ry」と思ったのと、Plack先生といちゃいちゃする練習として、車輪の再発明感ましましながらもPlackベースで作ってみました。
Plack::App::Proxy::Selective
http://github.com/zentooo/p5-plack-app-proxy-selective
名前はまんまパクリ。Plack周りをいじったことのあるお方なら薄々お気づきかもしれませんが、内部でPlack::App::DirectoryとPlack::App::Proxyに振っているだけです。
使いかた
基本的にはこんな感じに使います。
use strict; use warnings; use Plack::App::Proxy::Selective; use Path::Class; Plack::App::Proxy::Selective->new( filter => +{ 'google.com' => +{ '/style' => 'css', }, 'www.yahoo.co.jp' => +{ 'js' => 'script', }, }, base_dir => file(__FILE__)->dir, )->to_app;
newの名前付き引数filterに設定値としてのハッシュリファレンスを、base_dirにローカルのドキュメントのルートとしてPath::Class::Dirのインスタンスを渡してやります。後は、このファイルをproxy.psgiとか適当な名前で保存して
plackup -p 8080 proxy.psgi
するだけ。
このローカルプロキシをhttp接続に用いるプロキシとしてブラウザに設定すると、あらふしぎ!指定したドメイン以下の指定したディレクトリ以下のファイルが、そっくりそのままローカルのファイルで置き換わります。ちなみに僕は、proxyのON/OFFはVimperatorのautoproxychanger.jsで切り替えています。
ちなみにパス名とかは正規表現に対応しているので、こんなこともできます。
Plack::App::Proxy::Selective->new( filter => +{ 'google.com' => +{ '/css/.*/' => '/style/', '/script/.*' => '/js/ext/', '/js/.*\.js' => '/js/ext/', }, }, base_dir => file(__FILE__)->dir, )->to_app;
上から順に、
- css/なんとか/ 以下のファイルを全部ローカルのカレントディレクトリ/style 以下のファイルに置き換える(css/ 直下は置き換わらない)
- /script/ 以下のファイルを$PWD/js/ext/ 以下のファイルに置き換える(これだと/script/って書くのと同じ)
- /js 以下の、jsファイルのみ$PWD/js/ext/ 以下のファイルに置き換える(/js/hoge.css とかは置き換わらない)
あと多分あんまやらないと思うけど、
Plack::App::Proxy::Selective->new( filter => +{ 'google.com' => +{ '.*\.js' => '/script/', }, }, base_dir => file(__FILE__)->dir, )->to_app;
という書き方をすると、当然ながらサーバ上の全jsファイルがローカルのscript以下のものに置き換えられる。
現状の問題点
- コードが汚い
Perl慣れしてない&手探りで書いたのでコードがいけてない。というか、ハッシュリファレンスをイテレートするスマートなやり方がよくわからん。while ( my ($key, $value) = each %$hashref ) ってやると何かへんなことになるし。誰か教えてちょんまげ!
↓
追記:
正確には while ( my ($key, $value) = each %{$self->filter} ) {} が動いていなかった。コメント欄参照。
- hoge.js.bakとかは無理
「ファイル名とは"foo.bar"みたいな文字列である」と内部で勝手に決め込んでいるので、hoge.js.bakとか拡張子の2個以上ついたファイルに現状対応できていない。いらん気もするけど。
- 正規表現周りがあやしい
予想されるユースケースに関しては一応テスト書いたけど、正規表現によっては変なことになるかも。
- デバッグ出力がない
そのうちつけましょう。
4つめ
これで、会社のMacで立ち上げるPlackアプリが4つになりますね!