From: Makoto Kuwata Date: 2008-02-04T04:40:16+09:00 Subject: [ruby-dev:33580] Re: cgi.rb再構築案 桑田といいます。 > るびきちです。 > > cgi.rbのCGI::TagMaker、CGI::HtmlExtension等を使っている人はいるでしょうか? > あまり使われていないのであれば、cgi/html.rbとかに分離したほうがいい気がします。 > > また、CGI::escape系はcgi/escape.rbに分離して、cgi.rbでrequireすれば > cgi/escape単独で使用する場合はコンパクトになります。どうでしょうか? 参考までに、cgi.rbを書き換えた CGIAlt というのを作ってます。 http://cgialt.rubyforge.org/ cgi.rbを以下のように分解してます。 * cgialt.rb * cgialt/core.rb * cgialt/util.rb * cgialt/cookie.rb * cgialt/html.rb また CGI.escapeHTML や CGI.unescape を拡張ライブラリで書き直しています。 http://cgiext.rubyforge.org/ 書き直して分かったこと: (1) CGI.unescape() が遅いせいで、request parameter や cookie の デコードが遅い → 解決策: CGI.unescape() を拡張ライブラリで書き直す (2) CGI.escapeHTML() が遅いので、PHPの htmlspecialchars() と比べて不利 → 解決策: CGI.escapeHTML() を拡張ライブラリで書き直す (3) CGI::Cookie class が DelegateClass(Array) を使っているせいで、 require 'cgi' にすごく時間がかかる (ruby の起動より時間がかかる)。 (時間がかかるのは CGI::HtmlExtention まわりのせいではない) → 解決策: DelegateClass(Array) を使わないように書き換える (4) multipart のときに、データサイズを確認せず受信してるので、 極めて大きいファイルを送信されるとサーバ資源を食いつぶす → 解決策: 受信するデータサイズの上限を設定する (5) multipart のときに、filename のある・なしに関係なく、値を Tempfile や StringIO に格納している。本来なら filename の ある値のみ Tempfile を使い、そうでないなら普通に String で よいはず → 解決策: インターフェースを変えないといけないので、解決は難しい (6) CGI#initialize() の中で ENV['QUERY_STRING'] や ENV['HTTP_COOKIE'] を parse しているので、FastCGI のように ENV を使わない場合、 cgi.rb を使うのが困難 (実際、fcgi.rb での cgi.rb 対策は悲惨なコードになっている) → 解決策: workaround として、$ENV = ENV をしてから、 CGI#initialize() では ENV のかわりに $ENV を使うように変更 (7) mod_ruby 対応がやっつけ仕事で効率が悪い → 解決策: 最初から mod_ruby 対応を考えて書き直す (8) テストスクリプトがまったく用意されていない → 解決策: 地道にテストスクリプトを書く (CGIAlt には添付済) (1)と(2)は pure Ruby では解決しにくい問題なので、拡張ライブラリを 使うのがいいと思います。というか、パフォーマンスのために基本的な 関数は拡張ライブラリで提供してほしいところです。 (3)と(4)と(8)は今すぐにでも解決できる問題なので、対応を検討して いただけるとうれしいです。 # 以前、(8) を提案したときにまったくの無反応だったのですが、 # 誰も興味ないのでしょうか。 書き直して思ったのは、cgi.rbを書き直したところで良くならないと いうことです。1.9 を見据えて、cgi.rb の代替物を広く公募しては いかがでしょうか。 PHP を dis ってる場合じゃないです。 -- makoto kuwata