From 4f05fb1a3b44f8eab1a9dda26d5b115f33a149cd Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Mon, 29 Jun 2009 05:27:18 -0700 Subject: configurator: provide stream_input (true|false) option The default is false because some applications were not written to handle partial reads (even though IO#read allows it, not just IO#readpartial). --- lib/unicorn/configurator.rb | 29 ++++++++++++++++++++++++++++- lib/unicorn/http_request.rb | 5 ----- test/unit/test_configurator.rb | 4 +++- 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/lib/unicorn/configurator.rb b/lib/unicorn/configurator.rb index a432f64..99a3c04 100644 --- a/lib/unicorn/configurator.rb +++ b/lib/unicorn/configurator.rb @@ -44,6 +44,7 @@ module Unicorn :preload_app => false, :stderr_path => nil, :stdout_path => nil, + :stream_input => false, } attr_reader :config_file #:nodoc: @@ -64,8 +65,12 @@ module Unicorn def commit!(server, options = {}) #:nodoc: skip = options[:skip] || [] + stream_input = @set.delete(:stream_input) + unless stream_input.nil? + Unicorn::HttpRequest::DEFAULTS[Const::STREAM_INPUT] = stream_input + end @set.each do |key, value| - (Symbol === value && value == :unset) and next + value == :unset and next skip.include?(key) and next setter = "#{key}=" if server.respond_to?(setter) @@ -249,6 +254,28 @@ module Unicorn end end + # Allow applications to stream input as it is being read from the + # network directly to the application. Enabling this can allow + # real-time processing of request bodies as it is being sent by + # the client, useful for things like upload progress notification + # and tunneling arbitrary stream protocols via bidirectional chunked + # transfer encoding. + # This may not work with all applications because some broken + # applications assume env['rack.input'].read(size) always returns + # the requested amount of data. This causes env['rack.input']#read + # to provide IO#readpartial semantics instead. Some applications + # may also fully receive an input and never attempt to process it, + # causing clients confusion when they receive a response after + # only a partial request has been sent. + def stream_input(bool) + case bool + when TrueClass, FalseClass + @set[:stream_input] = bool + else + raise ArgumentError, "stream_input=#{bool.inspect} not a boolean" + end + end + # Allow redirecting $stderr to a given path. Unlike doing this from # the shell, this allows the unicorn process to know the path its # writing to and rotate the file if it is used for logging. The diff --git a/lib/unicorn/http_request.rb b/lib/unicorn/http_request.rb index e25517b..b1cd8ed 100644 --- a/lib/unicorn/http_request.rb +++ b/lib/unicorn/http_request.rb @@ -17,11 +17,6 @@ module Unicorn "rack.version" => [1, 0].freeze, "SCRIPT_NAME" => "".freeze, - # some applications (like Echo) may want to change this to true - # We disable streaming by default since some (arguably broken) - # applications may not ever read the entire body and be confused - # when it receives a response after nothing has been sent to it. - Const::STREAM_INPUT => false, # this is not in the Rack spec, but some apps may rely on it "SERVER_SOFTWARE" => "Unicorn #{Const::UNICORN_VERSION}".freeze } diff --git a/test/unit/test_configurator.rb b/test/unit/test_configurator.rb index 98f2db6..f836647 100644 --- a/test/unit/test_configurator.rb +++ b/test/unit/test_configurator.rb @@ -1,6 +1,6 @@ require 'test/unit' require 'tempfile' -require 'unicorn/configurator' +require 'unicorn' class TestConfigurator < Test::Unit::TestCase @@ -53,6 +53,7 @@ class TestConfigurator < Test::Unit::TestCase cfg = Unicorn::Configurator.new(:use_defaults => true) assert_nothing_raised { cfg.commit!(self) } Unicorn::Configurator::DEFAULTS.each do |key,value| + next if key == :stream_input assert_equal value, instance_variable_get("@#{key.to_s}") end end @@ -64,6 +65,7 @@ class TestConfigurator < Test::Unit::TestCase @logger = nil Unicorn::Configurator::DEFAULTS.each do |key,value| next if skip.include?(key) + next if key == :stream_input assert_equal value, instance_variable_get("@#{key.to_s}") end assert_nil @logger -- cgit v1.2.3-24-ge0c7