about summary refs log tree commit homepage
diff options
context:
space:
mode:
-rw-r--r--lib/rainbows.rb5
-rw-r--r--lib/rainbows/client.rb6
-rw-r--r--lib/rainbows/configurator.rb1
-rw-r--r--lib/rainbows/coolio/client.rb4
-rw-r--r--lib/rainbows/epoll/client.rb2
-rw-r--r--lib/rainbows/ev_core.rb1
-rw-r--r--lib/rainbows/http_server.rb6
-rw-r--r--lib/rainbows/process_client.rb3
-rw-r--r--lib/rainbows/xepoll_thread_spawn/client.rb5
-rw-r--r--t/client_header_buffer_size.ru3
-rw-r--r--t/t0042-client_header_buffer_size.sh65
11 files changed, 92 insertions, 9 deletions
diff --git a/lib/rainbows.rb b/lib/rainbows.rb
index 4b8d552..0e6ca39 100644
--- a/lib/rainbows.rb
+++ b/lib/rainbows.rb
@@ -67,6 +67,7 @@ module Rainbows
 
   # :stopdoc:
   class << self
+    attr_accessor :client_header_buffer_size
     attr_accessor :max_bytes, :keepalive_timeout
     attr_accessor :server
     attr_accessor :cur # may not always be used
@@ -81,6 +82,10 @@ module Rainbows
   # the default keepalive_timeout is 5 seconds
   @keepalive_timeout = 5
 
+  # 1024 bytes matches nginx, though Rails session cookies will typically
+  # need >= 1500...
+  @client_header_buffer_size = 1024
+
   # :stopdoc:
   @alive = true
   @cur = 0
diff --git a/lib/rainbows/client.rb b/lib/rainbows/client.rb
index 7387c44..4608f53 100644
--- a/lib/rainbows/client.rb
+++ b/lib/rainbows/client.rb
@@ -4,6 +4,8 @@ require "io/wait"
 
 # this class is used for most synchronous concurrency models
 class Rainbows::Client < Kgio::Socket
+  include Rainbows::ProcessClient
+
   def read_expire
     Time.now + Rainbows.keepalive_timeout
   end
@@ -16,7 +18,7 @@ class Rainbows::Client < Kgio::Socket
   def timed_read(buf)
     expire = nil
     begin
-      case rv = kgio_tryread(0x1000, buf)
+      case rv = kgio_tryread(HBUFSIZ, buf)
       when :wait_readable
         return if expire && expire < Time.now
         expire ||= read_expire
@@ -26,6 +28,4 @@ class Rainbows::Client < Kgio::Socket
       end
     end while true
   end
-
-  include Rainbows::ProcessClient
 end
diff --git a/lib/rainbows/configurator.rb b/lib/rainbows/configurator.rb
index 3203c5a..b596b0b 100644
--- a/lib/rainbows/configurator.rb
+++ b/lib/rainbows/configurator.rb
@@ -14,6 +14,7 @@ module Rainbows::Configurator
   #     keepalive_timeout 0 # zero disables keepalives entirely
   #     client_max_body_size 5*1024*1024 # 5 megabytes
   #     keepalive_requests 666 # default:100
+  #     client_header_buffer_size 16 * 1024 # 16 kilobytes
   #   end
   #
   #   # the rest of the Unicorn configuration
diff --git a/lib/rainbows/coolio/client.rb b/lib/rainbows/coolio/client.rb
index 2de421a..5688730 100644
--- a/lib/rainbows/coolio/client.rb
+++ b/lib/rainbows/coolio/client.rb
@@ -45,7 +45,7 @@ class Rainbows::Coolio::Client < Coolio::IO
   end
 
   def on_readable
-    buf = @_io.kgio_tryread(16384, RBUF)
+    buf = @_io.kgio_tryread(HBUFSIZ, RBUF)
     case buf
     when :wait_readable
     when nil # eof
@@ -134,7 +134,7 @@ class Rainbows::Coolio::Client < Coolio::IO
       close if @_write_buffer.empty?
     when :headers
       if @buf.empty?
-        buf = @_io.kgio_tryread(16384, RBUF) or return close
+        buf = @_io.kgio_tryread(HBUFSIZ, RBUF) or return close
         String === buf and return on_read(buf)
         # buf == :wait_readable
         unless enabled?
diff --git a/lib/rainbows/epoll/client.rb b/lib/rainbows/epoll/client.rb
index 924d32f..3fbd386 100644
--- a/lib/rainbows/epoll/client.rb
+++ b/lib/rainbows/epoll/client.rb
@@ -33,7 +33,7 @@ module Rainbows::Epoll::Client
   end
 
   def on_readable
-    case rv = kgio_tryread(16384, RBUF)
+    case rv = kgio_tryread(HBUFSIZ, RBUF)
     when String
       on_read(rv)
       return if @wr_queue[0] || closed?
diff --git a/lib/rainbows/ev_core.rb b/lib/rainbows/ev_core.rb
index 61853ab..24254dc 100644
--- a/lib/rainbows/ev_core.rb
+++ b/lib/rainbows/ev_core.rb
@@ -9,6 +9,7 @@ module Rainbows::EvCore
   autoload :CapInput, 'rainbows/ev_core/cap_input'
   RBUF = ""
   Z = "".freeze
+  HBUFSIZ = Rainbows.client_header_buffer_size
 
   # Apps may return this Rack response: AsyncResponse = [ -1, {}, [] ]
   ASYNC_CALLBACK = "async.callback".freeze
diff --git a/lib/rainbows/http_server.rb b/lib/rainbows/http_server.rb
index 4e1d7d9..c36b7bf 100644
--- a/lib/rainbows/http_server.rb
+++ b/lib/rainbows/http_server.rb
@@ -141,4 +141,10 @@ class Rainbows::HttpServer < Unicorn::HttpServer
     end
     Rainbows.max_bytes = nr
   end
+
+  def client_header_buffer_size(bytes)
+    Integer === bytes && bytes > 0 or raise ArgumentError,
+            "client_header_buffer_size must be a positive Integer"
+    Rainbows.client_header_buffer_size = bytes
+  end
 end
diff --git a/lib/rainbows/process_client.rb b/lib/rainbows/process_client.rb
index 6201064..f30aa5d 100644
--- a/lib/rainbows/process_client.rb
+++ b/lib/rainbows/process_client.rb
@@ -7,10 +7,11 @@ module Rainbows::ProcessClient
   NULL_IO = Unicorn::HttpRequest::NULL_IO
   RACK_INPUT = Unicorn::HttpRequest::RACK_INPUT
   IC = Unicorn::HttpRequest.input_class
+  HBUFSIZ = Rainbows.client_header_buffer_size
 
   def process_loop
     @hp = hp = Rainbows::HttpParser.new
-    kgio_read!(0x1000, buf = hp.buf) or return
+    kgio_read!(HBUFSIZ, buf = hp.buf) or return
 
     begin # loop
       until env = hp.parse
diff --git a/lib/rainbows/xepoll_thread_spawn/client.rb b/lib/rainbows/xepoll_thread_spawn/client.rb
index 9bee1d1..4111f27 100644
--- a/lib/rainbows/xepoll_thread_spawn/client.rb
+++ b/lib/rainbows/xepoll_thread_spawn/client.rb
@@ -4,6 +4,7 @@ require "sleepy_penguin"
 require "raindrops"
 
 module Rainbows::XEpollThreadSpawn::Client
+  HBUFSIZ = Rainbows.client_header_buffer_size
   N = Raindrops.new(1)
   max = Rainbows.server.worker_connections
   ACCEPTORS = Rainbows::HttpServer::LISTENERS.map do |sock|
@@ -88,7 +89,7 @@ module Rainbows::XEpollThreadSpawn::Client
   end
 
   def epoll_run(buf)
-    case kgio_tryread(0x1000, buf)
+    case kgio_tryread(HBUFSIZ, buf)
     when :wait_readable
       return kato_set
     when String
@@ -108,7 +109,7 @@ module Rainbows::XEpollThreadSpawn::Client
 
   def pipeline_ready(hp)
     env = hp.parse and return env
-    case buf = kgio_tryread(0x1000)
+    case buf = kgio_tryread(HBUFSIZ)
     when :wait_readable
       kato_set
       return false
diff --git a/t/client_header_buffer_size.ru b/t/client_header_buffer_size.ru
new file mode 100644
index 0000000..0831944
--- /dev/null
+++ b/t/client_header_buffer_size.ru
@@ -0,0 +1,3 @@
+use Rack::ContentLength
+use Rack::ContentType, "text/plain"
+run lambda { |env| [ 200, {}, [ "#{Rainbows.client_header_buffer_size}\n" ] ] }
diff --git a/t/t0042-client_header_buffer_size.sh b/t/t0042-client_header_buffer_size.sh
new file mode 100644
index 0000000..0e19361
--- /dev/null
+++ b/t/t0042-client_header_buffer_size.sh
@@ -0,0 +1,65 @@
+#!/bin/sh
+. ./test-lib.sh
+
+t_plan 8 "client_header_buffer_size tests for $model"
+
+t_begin "setup and startup" && {
+        rainbows_setup $model
+}
+
+t_begin "fails with zero buffer size" && {
+        ed -s $unicorn_config <<EOF
+,s/^  client_max_body_size.*/  client_header_buffer_size 0/
+w
+EOF
+        grep "client_header_buffer_size 0" $unicorn_config
+        rainbows -D client_header_buffer_size.ru -c $unicorn_config || \
+                echo err=$? > $ok
+        test x"$(cat $ok)" = "xerr=1"
+}
+
+t_begin "fails with negative value" && {
+        ed -s $unicorn_config <<EOF
+,s/^  client_header_buffer_size.*/  client_header_buffer_size -1/
+w
+EOF
+        grep "client_header_buffer_size -1" $unicorn_config
+        rainbows -D client_header_buffer_size.ru -c $unicorn_config || \
+                echo err=$? > $ok
+        test x"$(cat $ok)" = "xerr=1"
+}
+
+t_begin "fails with negative value" && {
+        ed -s $unicorn_config <<EOF
+,s/^  client_header_buffer_size.*/  client_header_buffer_size -1/
+w
+EOF
+        grep "client_header_buffer_size -1" $unicorn_config
+        rainbows -D client_header_buffer_size.ru -c $unicorn_config || \
+                echo err=$? > $ok
+        test x"$(cat $ok)" = "xerr=1"
+}
+
+t_begin "starts with correct value" && {
+        ed -s $unicorn_config <<EOF
+,s/^  client_header_buffer_size.*/  client_header_buffer_size 16399/
+w
+EOF
+        grep "client_header_buffer_size 16399" $unicorn_config
+        rainbows -D client_header_buffer_size.ru -c $unicorn_config
+        rainbows_wait_start
+}
+
+t_begin "regular TCP request works right" && {
+        test x$(curl -sSfv http://$listen/) = x16399
+}
+
+t_begin "no errors in stderr" && {
+        check_stderr
+}
+
+t_begin "shutdown" && {
+        kill $rainbows_pid
+}
+
+t_done