monolithic kernel

Rack 1.1.0をCGIで動作させる場合にPOSTが使えない問題への対処

RackをCGIとして使うときにPOSTで生じる問題は以前から存在していましたが、1.1.0では以前と同じ対処法が使えなかったのでメモしておきます。SinatraやRamazeもRackベースなのでこの対処法で動作するようになると思います。

この内容をrack_fix.rbなどとして保存しておいて、rack本体より後でrequireすればエラーを抑止することができます。

module Rack
  class Request
    def POST
      if @env["rack.input"].nil?
        raise "Missing rack.input"
      elsif @env["rack.request.form_input"].eql? @env["rack.input"]
        @env["rack.request.form_hash"]
      elsif form_data? || parseable_data?
        @env["rack.request.form_input"] = @env["rack.input"]
        unless @env["rack.request.form_hash"] = parse_multipart(env)
          form_vars = @env["rack.input"].read
          # Fix for Safari Ajax postings that always append \0
          form_vars.sub!(/\0\z/, '')
          @env["rack.request.form_vars"] = form_vars
          @env["rack.request.form_hash"] = parse_query(form_vars)
          begin
            @env["rack.input"].rewind
          rescue Lint::LintError
          end
        end
        @env["rack.request.form_hash"]
      else
        {}
      end
    end
  end
end

rewind時に飛ぶ例外を握りつぶしているのは以前と同じですが、1.1.0では例外の種類がこれまでのErrno::ESPIPEからRack::Lint::LintErrorに変更されたようなので対応しています。Rack::Lint::LintErrorは広く利用されているので握りつぶしていいのか微妙なところですが、今のところ問題は起きていません。