いずれ消え行く無駄な情報を、密やかに発信する装置。つまり日記。
Ruby1.9系で大量のファイルをアップロードするcgiスクリプトを書いてハマったことを書きます。
このblogの編集用に画像ファイルをサーバにアップロードするスクリプトを書いたのですが、ファイルが少ないと上手く動くものの、何故か数百Mのアップロードとなるとアップロードが完了してから落ちるという謎現象が起こりました。アップロード自体は成功しているので、Apacheではなくcgi側だと思ったのですが、cgi側も少数のファイルでは正常に動作することから問題の切り分けが難航。
そんな中、ひたすらgoogleで検索していると「るびま」のcgi.rb がイケてない 12 の理由がヒット。このなかで、ruby1.8系のcgi.rbは無制限にファイルを受け取れるという記述を発見。
cgi.rb では、受信する HTTP リクエストデータのサイズを確認していません。 そのため、例えば 10GB の動画ファイルを送られてきた場合、それを正直に受け取ってしまうため、サーバ資源を食い荒らされてしまいます。 これを防ぐには、Content-Length の値を確認し、大きすぎるようであれば受信しないようにする必要があります。 以下がそのためのパッチです*4。
この記事の中で、ruby1.8系のcgi.rbでリクエストパラメータの数とサイズを制限するパッチが書かれていました。ひょっとすると、ruby1.9系のcgi.rbにマージされたかと思い、1.9系 cgi/core.rbで検索をかけると予想通りマージされていました。
rubyのバージョンはruby 1.9.2p290 (2011-07-09 revision 32553) [amd64-freebsd8]
344 # Maximum content length of post data 345 ##MAX_CONTENT_LENGTH = 2 * 1024 * 1024 346 347 # Maximum content length of multipart data 348 MAX_MULTIPART_LENGTH = 128 * 1024 * 1024 349 350 # Maximum number of request parameters when multipart 351 MAX_MULTIPART_COUNT = 128
これにより、パラメータ数は128個。最大サイズは128MBまでということが判明。
これよりも増やしたい場合は、単純に定数の上書きをすれば良いようです。(定数をあとから上書きして良いのかという話はありますが・・・。本当ならば自分用のパッチでも当てた方がいいのかもしれません。)
require "cgi.rb" CGI::MAX_MULTIPART_LENGTH = 512 * 1024 * 1024 CGI::MAX_MULTIPART_COUNT = 512
cgi.rb がイケてない 12 の理由
[ruby-list:44296] multipartで送信した時のRails/cgi.rbの動作について