TurboGearsのVirtualHost化ではまりまくる¶
今日はTurboGearsのアプリをmod_proxyの陰で動かし、VirtualHostで任意のパス以下に配置しようとしてはまりまくってました。
たとえば http://example.com/myapp/ がTurboGearsアプリのルートになる場合、TurboGearsのプログラム上やテンプレート上には"myapp"は書かずに、cfgに server.webpath="myapp"
と書けばそれでOK!...と思ってました。それでは、はまり度の軽い方から並べてみます。
server.webpath="/myapp", base_url_filter.on = True をcfgに書く
テンプレート内のパスは ${tg.url('/hoge')}のようにtg.urlでくるむ
リダイレクトは turbogears.redirect('hoge') ではなく turbogears.redirect('/hoge')と書く
(1),(2)は基本、(3)は知らないと悩むことになりそう。redirect('hoge')だと http://example.com/hoge にリダイレクトされます。redirect('/hoge')ならちゃんと http://example.com/myapp/hoge にリダイレクトされます。
base_url_filter.use_x_forwarded_host = False を明示的に指定する
base_url_filter.base_url = "http://example.com/myapp" のようにmyappまで書く
(4),(5)は本当にこれで正しいのかアヤシイです。でもこうしないと http://example.com/myapp/hoge にアクセスしたときに http://example.com/hoge/ にリダイレクトされてしまいます。cherrypyはControllerオブジェクトにアクセスしたときはURL末尾に"/"が付くようにリダイレクトしようとします。しかし、リダイレクトのURL生成ではturbogearsのredirectやurl関数のようにmyappを考慮してくれません。この対処のため(4)で実サーバーURLの自動的検出をOFFにし、(5)でURLをmyapp付きで与えることにより、強制的にbase_urlを指定します。
いや、指定します、とか書いてますが、本当にこれでいいんだろうか‥‥。日英両方の文献を見てもこういう例が見あたらない気がします。みんなmod_pythonでやってて問題にならないからかな?
まとめ.
prod.cfg
server.webpath="/myapp"
base_url_filter.on = True
base_url_filter.use_x_forwarded_host = False
base_url_filter.base_url = "http://example.com/myapp"
httpd_tg.conf
<VirtualHost *:80>
ServerName example.com
RewriteEngine On
RewriteRule ^/myapp(/.*|$) http://localhost:8080$1 [P,L]
</VirtualHost>