2007年10月24日

lighttpd と scgi と fastcgi と


scgiとfcgiって、fcgiの方が多機能だけど、リクエスト時の動きは一緒と思ってたのだが、結構違った。



paster create -t paste_deploy で作成されるサンプルアプリケーションで、PATH_INFOを調べてみた結果です。


fcgiの場合



/a にマウント


http://localhost/a

PATH_INFO
''

SCIPT_NAME
'/a'



http://localhost/a/b

PATH_INFO
'/b'

SCIPT_NAME
'/a'



/ にマウント


http://localhost/

PATH_INFO
''

SCIPT_NAME
'/'


http://localhost/a

PATH_INFO
''

SCIPT_NAME
'/a'



scgiの場合



/a にマウント


http://localhost/a

PATH_INFO
'/a'

SCIPT_NAME
''



http://localhost/a/b

PATH_INFO
'/a/b'

SCIPT_NAME
''



/ にマウント


http://localhost/

PATH_INFO
'/'

SCIPT_NAME
''



http://localhost/a

PATH_INFO
'/a'

SCIPT_NAME
''




と、PATH_INFOとSCRIPT_NAMEの分け方が逆。



fcgiは全部SCRIPT_NAME側に振られるけど、scgiはPATH_INFOに振ってくる。



ただし、scgiの場合はscriptNameを設定できるわけで、scriptName=/a で、/a にマウントした場合が以下


http://localhost/a

PATH_INFO
''

SCIPT_NAME
'/a'



http://localhost/a/b

PATH_INFO
'/b'

SCIPT_NAME
'/a'




これはfcgiで、/a にマウントした場合と同じ振るまいをする。
scgiを使う場合はscriptNameのデフォルトが''なので、/a にマウントした場合は、pasteの設定でも/aをscriptNameにしないとだめ。



ところで、fcgiで/ にマウントした場合の挙動が非常に気になる。
すべて、SCRIPT_NAMEになってしまうのはいかがなものか。



scgiの挙動の方が正しく思える。
SCRIPT_NAMEは実体までのパスで、PATH_INFOはそれ以降の仮想的なパスという意味合いを持つ。
とすれば、同じWSGIアプリケーションに対するリクエストで、SCRIPT_NAMEが変わってしまうのは納得がいかない。
というか、WSGIで使われているディスパッチャはたいていPATH_INFOをみているわけで、うまく動かない。
Djangoでも、lightyの/にfcgiでマウントするとうまく動かなくなるという話を聞いているが、おそらくこれ原因じゃないだろうか。
/にマウントした場合、REQUEST_URIを使ってしのいでいるらしいが、おそらくSCRIPT_NAMEを使っても同様の動作となるだろう。



正しく動かすには、scgiでマウントさせるのが良さそうだ。
実際、Pylonsでも試してみたが、fcgiで/にマウントすると、うまく動かず、scgiに変更したら正常に動作した。