Rainbows! Rack HTTP server user/dev discussion
 help / Atom feed
* [WIP 0/5] updates for unicorn 5 internal changes
@ 2015-11-14  2:47 Eric Wong
  2015-11-14  2:47 ` [PATCH 1/5] http_parser: handle keepalive_requests internally Eric Wong
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Eric Wong @ 2015-11-14  2:47 UTC (permalink / raw)
  To: rainbows-public

Only passes tests (using unicorn 4.x) so far.  There is likely
more to do, but just publishing these changes early to give
folks some time to look at them over the weekend.

 lib/rainbows/const.rb                   |  3 --
 lib/rainbows/coolio/client.rb           | 10 +++----
 lib/rainbows/coolio/thread_client.rb    |  6 ++--
 lib/rainbows/dev_fd_response.rb         | 22 ++++++--------
 lib/rainbows/epoll/client.rb            | 10 +++----
 lib/rainbows/error.rb                   |  4 +--
 lib/rainbows/ev_core.rb                 | 28 +++++++-----------
 lib/rainbows/event_machine/client.rb    | 14 ++++-----
 lib/rainbows/event_machine/try_defer.rb |  5 +---
 lib/rainbows/http_parser.rb             | 24 ++++++++++++++++
 lib/rainbows/http_server.rb             |  4 +--
 lib/rainbows/max_body.rb                | 13 +++------
 lib/rainbows/process_client.rb          | 19 ++++++------
 lib/rainbows/response.rb                | 51 +++++++++++----------------------
 lib/rainbows/reverse_proxy.rb           | 28 ++++++------------
 lib/rainbows/reverse_proxy/ev_client.rb |  7 ++---
 lib/rainbows/sendfile.rb                | 12 ++------
 lib/rainbows/server_token.rb            |  7 +----
 lib/rainbows/stream_response_epoll.rb   | 13 ++++-----
 19 files changed, 119 insertions(+), 161 deletions(-)

[PATCH 1/5] http_parser: handle keepalive_requests internally
[PATCH 2/5] kill the moronic Status: header
[PATCH 3/5] reflect changes in Rack::Utils::HTTP_STATUS_CODES
[PATCH 4/5] reduce constant lookup dependencies
[PATCH 5/5] http_parser: workaround hijack changes in unicorn 5

^ permalink raw reply	[flat|threaded] 6+ messages in thread

* [PATCH 1/5] http_parser: handle keepalive_requests internally
  2015-11-14  2:47 [WIP 0/5] updates for unicorn 5 internal changes Eric Wong
@ 2015-11-14  2:47 ` Eric Wong
  2015-11-14  2:47 ` [PATCH 2/5] kill the moronic Status: header Eric Wong
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Eric Wong @ 2015-11-14  2:47 UTC (permalink / raw)
  To: rainbows-public

unicorn 5 dropped support for this, essentially allowing unlimited
persistent connections if we used the parser as-is.
Since most of our concurrency models cannot handle infinite
persistent connections without being vulnerable to DoS,
we must support keepalive_requests like nginx does.
---
 lib/rainbows/http_parser.rb | 15 +++++++++++++++
 lib/rainbows/http_server.rb |  4 ++--
 2 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/lib/rainbows/http_parser.rb b/lib/rainbows/http_parser.rb
index ec55fe9..30a67cb 100644
--- a/lib/rainbows/http_parser.rb
+++ b/lib/rainbows/http_parser.rb
@@ -2,6 +2,21 @@
 # :enddoc:
 # avoid modifying Unicorn::HttpParser
 class Rainbows::HttpParser < Unicorn::HttpParser
+  @keepalive_requests = 100
+  class << self
+    attr_accessor :keepalive_requests
+  end
+
+  def initialize(*args)
+    @keepalive_requests = self.class.keepalive_requests
+    super
+  end
+
+  def next?
+    return false if (@keepalive_requests -= 1) <= 0
+    super
+  end
+
   def self.quit
     alias_method :next?, :never!
   end
diff --git a/lib/rainbows/http_server.rb b/lib/rainbows/http_server.rb
index 637710d..09f2589 100644
--- a/lib/rainbows/http_server.rb
+++ b/lib/rainbows/http_server.rb
@@ -92,11 +92,11 @@ class Rainbows::HttpServer < Unicorn::HttpServer
   end
 
   def keepalive_requests=(nr)
-    Unicorn::HttpRequest.keepalive_requests = nr
+    Rainbows::HttpParser.keepalive_requests = nr
   end
 
   def keepalive_requests
-    Unicorn::HttpRequest.keepalive_requests
+    Rainbows::HttpParser.keepalive_requests
   end
 
   def client_max_header_size=(bytes)
-- 
EW


^ permalink raw reply	[flat|threaded] 6+ messages in thread

* [PATCH 2/5] kill the moronic Status: header
  2015-11-14  2:47 [WIP 0/5] updates for unicorn 5 internal changes Eric Wong
  2015-11-14  2:47 ` [PATCH 1/5] http_parser: handle keepalive_requests internally Eric Wong
@ 2015-11-14  2:47 ` Eric Wong
  2015-11-14  2:47 ` [PATCH 3/5] reflect changes in Rack::Utils::HTTP_STATUS_CODES Eric Wong
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Eric Wong @ 2015-11-14  2:47 UTC (permalink / raw)
  To: rainbows-public

Whatever compatibility reasons which existed in 2009 likely do not exist
now.  Other servers (e.g. thin, puma) seem to work alright without it,
so there's no reason to waste precious bytes.
---
 lib/rainbows/response.rb              | 3 +--
 lib/rainbows/stream_response_epoll.rb | 2 +-
 2 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/lib/rainbows/response.rb b/lib/rainbows/response.rb
index b7b6aa8..db14ee4 100644
--- a/lib/rainbows/response.rb
+++ b/lib/rainbows/response.rb
@@ -42,8 +42,7 @@ module Rainbows::Response
     hijack = nil
     status = CODES[status.to_i] || status
     buf = "HTTP/1.1 #{status}\r\n" \
-          "Date: #{httpdate}\r\n" \
-          "Status: #{status}\r\n"
+          "Date: #{httpdate}\r\n"
     headers.each do |key, value|
       case key
       when %r{\A(?:Date\z|Connection\z)}i
diff --git a/lib/rainbows/stream_response_epoll.rb b/lib/rainbows/stream_response_epoll.rb
index 33d7386..c0d90a4 100644
--- a/lib/rainbows/stream_response_epoll.rb
+++ b/lib/rainbows/stream_response_epoll.rb
@@ -31,7 +31,7 @@ module Rainbows::StreamResponseEpoll
     if headers
       # don't set extra headers here, this is only intended for
       # consuming by nginx.
-      buf = "HTTP/1.0 #{status}\r\nStatus: #{status}\r\n"
+      buf = "HTTP/1.0 #{status}\r\n"
       headers.each do |key, value|
         case key
         when "rack.hijack"
-- 
EW


^ permalink raw reply	[flat|threaded] 6+ messages in thread

* [PATCH 3/5] reflect changes in Rack::Utils::HTTP_STATUS_CODES
  2015-11-14  2:47 [WIP 0/5] updates for unicorn 5 internal changes Eric Wong
  2015-11-14  2:47 ` [PATCH 1/5] http_parser: handle keepalive_requests internally Eric Wong
  2015-11-14  2:47 ` [PATCH 2/5] kill the moronic Status: header Eric Wong
@ 2015-11-14  2:47 ` Eric Wong
  2015-11-14  2:47 ` [PATCH 4/5] reduce constant lookup dependencies Eric Wong
  2015-11-14  2:47 ` [PATCH 5/5] http_parser: workaround hijack changes in unicorn 5 Eric Wong
  4 siblings, 0 replies; 6+ messages in thread
From: Eric Wong @ 2015-11-14  2:47 UTC (permalink / raw)
  To: rainbows-public

Applications may want to alter the message associated with HTTP
status codes in Rack::Utils::HTTP_STATUS_CODES.  Avoid memoizing
status lines ahead-of-time

Note: this introduces a minor performance regression, but ought to
be unnoticeable unless you're running "Hello world"-type apps.
---
 lib/rainbows/response.rb              | 5 +++--
 lib/rainbows/stream_response_epoll.rb | 6 +++---
 2 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/lib/rainbows/response.rb b/lib/rainbows/response.rb
index db14ee4..a661ab6 100644
--- a/lib/rainbows/response.rb
+++ b/lib/rainbows/response.rb
@@ -40,8 +40,9 @@ module Rainbows::Response
   def write_headers(status, headers, alive, body)
     @hp.headers? or return body
     hijack = nil
-    status = CODES[status.to_i] || status
-    buf = "HTTP/1.1 #{status}\r\n" \
+    code = status.to_i
+    msg = Rack::Utils::HTTP_STATUS_CODES[code]
+    buf = "HTTP/1.1 #{msg ? %Q(#{code} #{msg}) : status}\r\n" \
           "Date: #{httpdate}\r\n"
     headers.each do |key, value|
       case key
diff --git a/lib/rainbows/stream_response_epoll.rb b/lib/rainbows/stream_response_epoll.rb
index c0d90a4..1f32dcc 100644
--- a/lib/rainbows/stream_response_epoll.rb
+++ b/lib/rainbows/stream_response_epoll.rb
@@ -20,18 +20,18 @@ require "raindrops"
 # * sleepy_penguin 3.0.1 or later
 module Rainbows::StreamResponseEpoll
   # :stopdoc:
-  CODES = Unicorn::HttpResponse::CODES
   HEADER_END = "X-Accel-Buffering: no\r\n\r\n"
   autoload :Client, "rainbows/stream_response_epoll/client"
 
   def http_response_write(socket, status, headers, body)
-    status = CODES[status.to_i] || status
     hijack = ep_client = false
 
     if headers
       # don't set extra headers here, this is only intended for
       # consuming by nginx.
-      buf = "HTTP/1.0 #{status}\r\n"
+      code = status.to_i
+      msg = Rack::Utils::HTTP_STATUS_CODES[code]
+      buf = "HTTP/1.0 #{msg ? %Q(#{code} #{msg}) : status}\r\n"
       headers.each do |key, value|
         case key
         when "rack.hijack"
-- 
EW


^ permalink raw reply	[flat|threaded] 6+ messages in thread

* [PATCH 4/5] reduce constant lookup dependencies
  2015-11-14  2:47 [WIP 0/5] updates for unicorn 5 internal changes Eric Wong
                   ` (2 preceding siblings ...)
  2015-11-14  2:47 ` [PATCH 3/5] reflect changes in Rack::Utils::HTTP_STATUS_CODES Eric Wong
@ 2015-11-14  2:47 ` Eric Wong
  2015-11-14  2:47 ` [PATCH 5/5] http_parser: workaround hijack changes in unicorn 5 Eric Wong
  4 siblings, 0 replies; 6+ messages in thread
From: Eric Wong @ 2015-11-14  2:47 UTC (permalink / raw)
  To: rainbows-public

Unicorn 5 removes some constants we were using, and constant
lookups + inline caching are waste of time anyways on newer
Rubies with the opt_str_freeze bytecode instruction.

This may reduce performance for folks on older Rubies (probably
not noticeable); but improves performance for folks on newer
Rubies.
---
 lib/rainbows/const.rb                   |  3 ---
 lib/rainbows/coolio/client.rb           |  8 ++++----
 lib/rainbows/coolio/thread_client.rb    |  4 ++--
 lib/rainbows/dev_fd_response.rb         | 22 ++++++++--------------
 lib/rainbows/epoll/client.rb            |  8 ++++----
 lib/rainbows/error.rb                   |  4 ++--
 lib/rainbows/ev_core.rb                 | 28 +++++++++++-----------------
 lib/rainbows/event_machine/client.rb    | 12 ++++++------
 lib/rainbows/event_machine/try_defer.rb |  5 +----
 lib/rainbows/max_body.rb                | 13 ++++---------
 lib/rainbows/process_client.rb          | 15 +++++++--------
 lib/rainbows/response.rb                | 29 +++++++++++------------------
 lib/rainbows/reverse_proxy.rb           | 28 +++++++++-------------------
 lib/rainbows/reverse_proxy/ev_client.rb |  7 ++-----
 lib/rainbows/sendfile.rb                | 12 +++---------
 lib/rainbows/server_token.rb            |  7 +------
 lib/rainbows/stream_response_epoll.rb   |  7 +++----
 17 files changed, 78 insertions(+), 134 deletions(-)

diff --git a/lib/rainbows/const.rb b/lib/rainbows/const.rb
index 8db95c0..14c7a44 100644
--- a/lib/rainbows/const.rb
+++ b/lib/rainbows/const.rb
@@ -13,7 +13,4 @@ module Rainbows::Const
     # if they're the response body.  Unset by default.
     # "rainbows.autochunk" => false,
   })
-
-  RACK_INPUT = Unicorn::HttpRequest::RACK_INPUT
-  REMOTE_ADDR = Unicorn::HttpRequest::REMOTE_ADDR
 end
diff --git a/lib/rainbows/coolio/client.rb b/lib/rainbows/coolio/client.rb
index 843f574..c05fd3a 100644
--- a/lib/rainbows/coolio/client.rb
+++ b/lib/rainbows/coolio/client.rb
@@ -122,9 +122,9 @@ class Rainbows::Coolio::Client < Coolio::IO
   def app_call input
     KATO.delete(self)
     disable if enabled?
-    @env[RACK_INPUT] = input
-    @env[REMOTE_ADDR] = @_io.kgio_addr
-    @env[ASYNC_CALLBACK] = method(:write_async_response)
+    @env['rack.input'] = input
+    @env['REMOTE_ADDR'] = @_io.kgio_addr
+    @env['async.callback'] = method(:write_async_response)
     @hp.hijack_setup(@env, @_io)
     status, headers, body = catch(:async) {
       APP.call(@env.merge!(RACK_DEFAULTS))
@@ -157,7 +157,7 @@ class Rainbows::Coolio::Client < Coolio::IO
           KATO[self] = Time.now
         end
       else
-        on_read(Z)
+        on_read(''.freeze)
       end
     end
     rescue => e
diff --git a/lib/rainbows/coolio/thread_client.rb b/lib/rainbows/coolio/thread_client.rb
index ee9fa04..4de705f 100644
--- a/lib/rainbows/coolio/thread_client.rb
+++ b/lib/rainbows/coolio/thread_client.rb
@@ -8,7 +8,7 @@ class Rainbows::Coolio::ThreadClient < Rainbows::Coolio::Client
   def app_call input
     KATO.delete(self)
     disable if enabled?
-    @env[RACK_INPUT] = input
+    @env['rack.input'] = input
     app_dispatch # must be implemented by subclass
   end
 
@@ -25,7 +25,7 @@ class Rainbows::Coolio::ThreadClient < Rainbows::Coolio::Client
   # here because that could cause a deadlock and we'd leak FDs
   def app_response
     begin
-      @env[REMOTE_ADDR] = @_io.kgio_addr
+      @env['REMOTE_ADDR'] = @_io.kgio_addr
       @hp.hijack_setup(@env, @_io)
       APP.call(@env.merge!(RACK_DEFAULTS))
     rescue => e
diff --git a/lib/rainbows/dev_fd_response.rb b/lib/rainbows/dev_fd_response.rb
index 7baccfc..8ebaabd 100644
--- a/lib/rainbows/dev_fd_response.rb
+++ b/lib/rainbows/dev_fd_response.rb
@@ -11,12 +11,6 @@ class Rainbows::DevFdResponse < Struct.new(:app)
 
   # :stopdoc:
   FD_MAP = Rainbows::FD_MAP
-  Content_Length = "Content-Length".freeze
-  Transfer_Encoding = "Transfer-Encoding".freeze
-  Rainbows_autochunk = "rainbows.autochunk".freeze
-  Rainbows_model = "rainbows.model"
-  HTTP_VERSION = "HTTP_VERSION"
-  Chunked = "chunked"
   include Rack::Utils
 
   # Rack middleware entry point, we'll just pass through responses
@@ -40,23 +34,23 @@ class Rainbows::DevFdResponse < Struct.new(:app)
     fileno = io.fileno
     FD_MAP[fileno] = io
     if st.file?
-      headers[Content_Length] ||= st.size.to_s
-      headers.delete(Transfer_Encoding)
+      headers['Content-Length'.freeze] ||= st.size.to_s
+      headers.delete('Transfer-Encoding'.freeze)
     elsif st.pipe? || st.socket? # epoll-able things
-      unless headers.include?(Content_Length)
-        if env[Rainbows_autochunk]
-          case env[HTTP_VERSION]
+      unless headers.include?('Content-Length'.freeze)
+        if env['rainbows.autochunk']
+          case env['HTTP_VERSION']
           when "HTTP/1.0", nil
           else
-            headers[Transfer_Encoding] = Chunked
+            headers['Transfer-Encoding'.freeze] = 'chunked'
           end
         else
-          env[Rainbows_autochunk] = false
+          env['rainbows.autochunk'] = false
         end
       end
 
       # we need to make sure our pipe output is Fiber-compatible
-      case env[Rainbows_model]
+      case env['rainbows.model']
       when :FiberSpawn, :FiberPool, :RevFiberSpawn, :CoolioFiberSpawn
         io.respond_to?(:kgio_wait_readable) or
           io = Rainbows::Fiber::IO.new(io)
diff --git a/lib/rainbows/epoll/client.rb b/lib/rainbows/epoll/client.rb
index 65fcb3e..2d95a99 100644
--- a/lib/rainbows/epoll/client.rb
+++ b/lib/rainbows/epoll/client.rb
@@ -63,8 +63,8 @@ module Rainbows::Epoll::Client
   end
 
   def app_call input # called by on_read()
-    @env[RACK_INPUT] = input
-    @env[REMOTE_ADDR] = kgio_addr
+    @env['rack.input'] = input
+    @env['REMOTE_ADDR'] = kgio_addr
     @hp.hijack_setup(@env, self)
     status, headers, body = APP.call(@env.merge!(RACK_DEFAULTS))
     return hijacked if @hp.hijacked?
@@ -93,7 +93,7 @@ module Rainbows::Epoll::Client
                     Rainbows::Epoll::ResponsePipe).new(io, self, body)
     return @wr_queue << pipe if @wr_queue[0]
     stream_pipe(pipe) or return
-    @wr_queue[0] or @wr_queue << Z
+    @wr_queue[0] or @wr_queue << ''.freeze
   end
 
   def ev_write_response(status, headers, body, alive)
@@ -120,7 +120,7 @@ module Rainbows::Epoll::Client
       want_more
     else
       # pipelined request (already in buffer)
-      on_read(Z)
+      on_read(''.freeze)
       return if @wr_queue[0] || closed?
       return hijacked if @hp.hijacked?
       close if :close == @state
diff --git a/lib/rainbows/error.rb b/lib/rainbows/error.rb
index 736d5d8..3686eab 100644
--- a/lib/rainbows/error.rb
+++ b/lib/rainbows/error.rb
@@ -28,11 +28,11 @@ module Rainbows::Error
          Errno::EBADF, Errno::ENOTCONN, Errno::ETIMEDOUT, Errno::EHOSTUNREACH
       # swallow error if client shuts down one end or disconnects
     when Unicorn::HttpParserError
-      Rainbows::Const::ERROR_400_RESPONSE # try to tell the client they're bad
+      "HTTP/1.1 400 Bad Request\r\n\r\n" # try to tell the client they're bad
     when IOError # HttpParserError is an IOError
     else
       app(e)
-      Rainbows::Const::ERROR_500_RESPONSE
+      "HTTP/1.1 500 Internal Server Error\r\n\r\n"
     end
   end
 end
diff --git a/lib/rainbows/ev_core.rb b/lib/rainbows/ev_core.rb
index 5c3c5b8..fd33786 100644
--- a/lib/rainbows/ev_core.rb
+++ b/lib/rainbows/ev_core.rb
@@ -8,13 +8,9 @@ module Rainbows::EvCore
   HttpParser = Rainbows::HttpParser
   autoload :CapInput, 'rainbows/ev_core/cap_input'
   RBUF = ""
-  Z = "".freeze
   Rainbows.config!(self, :client_header_buffer_size)
-  HTTP_VERSION = "HTTP_VERSION"
 
   # Apps may return this Rack response: AsyncResponse = [ -1, {}, [] ]
-  ASYNC_CALLBACK = "async.callback".freeze
-  ASYNC_CLOSE = "async.close".freeze
 
   def write_async_response(response)
     status, headers, body = response
@@ -23,8 +19,8 @@ module Rainbows::EvCore
       # "Transfer-Encoding: chunked", and the async.callback stuff
       # isn't Rack::Lint-compatible, so we have to enforce it here.
       headers = Rack::Utils::HeaderHash.new(headers) unless Hash === headers
-      alive = headers.include?(Content_Length) ||
-              !!(%r{\Achunked\z}i =~ headers[Transfer_Encoding])
+      alive = headers.include?('Content-Length'.freeze) ||
+              !!(%r{\Achunked\z}i =~ headers['Transfer-Encoding'.freeze])
     end
     @deferred = nil
     ev_write_response(status, headers, body, alive)
@@ -55,12 +51,12 @@ module Rainbows::EvCore
   # returns nil if request was hijacked in response stage
   def stream_response_headers(status, headers, alive, body)
     headers = Rack::Utils::HeaderHash.new(headers) unless Hash === headers
-    if headers.include?(Content_Length)
+    if headers.include?('Content-Length'.freeze)
       write_headers(status, headers, alive, body) or return
       return false
     end
 
-    case @env[HTTP_VERSION]
+    case @env['HTTP_VERSION']
     when "HTTP/1.0" # disable HTTP/1.0 keepalive to stream
       write_headers(status, headers, false, body) or return
       @hp.clear
@@ -68,7 +64,7 @@ module Rainbows::EvCore
     when nil # "HTTP/0.9"
       false
     else
-      rv = !!(headers[Transfer_Encoding] =~ %r{\Achunked\z}i)
+      rv = !!(headers['Transfer-Encoding'] =~ %r{\Achunked\z}i)
       rv = false unless @env["rainbows.autochunk"]
       write_headers(status, headers, alive, body) or return
       rv
@@ -78,14 +74,14 @@ module Rainbows::EvCore
   def prepare_request_body
     # since we don't do streaming input, we have no choice but
     # to take over 100-continue handling from the Rack application
-    if @env[HTTP_EXPECT] =~ /\A100-continue\z/i
-      write(EXPECT_100_RESPONSE)
-      @env.delete(HTTP_EXPECT)
+    if @env['HTTP_EXPECT'] =~ /\A100-continue\z/i
+      write("HTTP/1.1 100 Continue\r\n\r\n".freeze)
+      @env.delete('HTTP_EXPECT'.freeze)
     end
     @input = mkinput
     @hp.filter_body(@buf2 = "", @buf)
     @input << @buf2
-    on_read(Z)
+    on_read(''.freeze)
   end
 
   # TeeInput doesn't map too well to this right now...
@@ -111,7 +107,7 @@ module Rainbows::EvCore
       elsif data.size > 0
         @hp.filter_body(@buf2, @buf << data)
         @input << @buf2
-        on_read(Z)
+        on_read(''.freeze)
       else
         want_more
       end
@@ -127,10 +123,8 @@ module Rainbows::EvCore
       handle_error(e)
   end
 
-  ERROR_413_RESPONSE = "HTTP/1.1 413 Request Entity Too Large\r\n\r\n"
-
   def err_413(msg)
-    write(ERROR_413_RESPONSE)
+    write("HTTP/1.1 413 Request Entity Too Large\r\n\r\n".freeze)
     quit
     # zip back up the stack
     raise IOError, msg, []
diff --git a/lib/rainbows/event_machine/client.rb b/lib/rainbows/event_machine/client.rb
index 9871c09..7fb88f6 100644
--- a/lib/rainbows/event_machine/client.rb
+++ b/lib/rainbows/event_machine/client.rb
@@ -23,7 +23,7 @@ class Rainbows::EventMachine::Client < EM::Connection
       end
       EM.next_tick { receive_data(nil) } unless @buf.empty?
     else
-      on_read(data || Z) if (@buf.size > 0) || data
+      on_read(data || ''.freeze) if (@buf.size > 0) || data
     end
   end
 
@@ -34,10 +34,10 @@ class Rainbows::EventMachine::Client < EM::Connection
 
   def app_call input
     set_comm_inactivity_timeout 0
-    @env[RACK_INPUT] = input
-    @env[REMOTE_ADDR] = @_io.kgio_addr
-    @env[ASYNC_CALLBACK] = method(:write_async_response)
-    @env[ASYNC_CLOSE] = EM::DefaultDeferrable.new
+    @env['rack.input'] = input
+    @env['REMOTE_ADDR'] = @_io.kgio_addr
+    @env['async.callback'] = method(:write_async_response)
+    @env['async.close'] = EM::DefaultDeferrable.new
     @hp.hijack_setup(@env, @_io)
     status, headers, body = catch(:async) {
       APP.call(@env.merge!(RACK_DEFAULTS))
@@ -117,7 +117,7 @@ class Rainbows::EventMachine::Client < EM::Connection
 
   def unbind
     return if @hp.hijacked?
-    async_close = @env[ASYNC_CLOSE] and async_close.succeed
+    async_close = @env['async.close'] and async_close.succeed
     @deferred.respond_to?(:fail) and @deferred.fail
     begin
       @_io.close
diff --git a/lib/rainbows/event_machine/try_defer.rb b/lib/rainbows/event_machine/try_defer.rb
index 615adae..778f3d0 100644
--- a/lib/rainbows/event_machine/try_defer.rb
+++ b/lib/rainbows/event_machine/try_defer.rb
@@ -10,9 +10,6 @@
 # See http://brainspl.at/articles/2008/04/18/deferred-requests-with-merb-ebb-and-thin
 # for more information.
 class Rainbows::EventMachine::TryDefer
-  # shortcuts
-  ASYNC_CALLBACK = Rainbows::EvCore::ASYNC_CALLBACK # :nodoc:
-
   def initialize(app) # :nodoc:
     # the entire app becomes multithreaded, even the root (non-deferred)
     # thread since any thread can share processes with others
@@ -22,7 +19,7 @@ class Rainbows::EventMachine::TryDefer
 
   def call(env) # :nodoc:
     if @app.deferred?(env)
-      EM.defer(proc { catch(:async) { @app.call(env) } }, env[ASYNC_CALLBACK])
+      EM.defer(proc { catch(:async) { @app.call(env) } }, env['async.callback'])
       # all of the async/deferred stuff breaks Rack::Lint :<
       nil
     else
diff --git a/lib/rainbows/max_body.rb b/lib/rainbows/max_body.rb
index a8abbf7..56a77ab 100644
--- a/lib/rainbows/max_body.rb
+++ b/lib/rainbows/max_body.rb
@@ -48,19 +48,14 @@ class Rainbows::MaxBody
     @app, @limit = app, limit
   end
 
-  # :stopdoc:
-  RACK_INPUT = "rack.input".freeze
-  CONTENT_LENGTH = "CONTENT_LENGTH"
-  HTTP_TRANSFER_ENCODING = "HTTP_TRANSFER_ENCODING"
-
   # our main Rack middleware endpoint
   def call(env)
     @limit = Rainbows.server.client_max_body_size if nil == @limit
     catch(:rainbows_EFBIG) do
-      len = env[CONTENT_LENGTH]
+      len = env['CONTENT_LENGTH']
       if len && len.to_i > @limit
         return err
-      elsif /\Achunked\z/i =~ env[HTTP_TRANSFER_ENCODING]
+      elsif /\Achunked\z/i =~ env['HTTP_TRANSFER_ENCODING']
         limit_input!(env)
       end
       @app.call(env)
@@ -89,9 +84,9 @@ class Rainbows::MaxBody
   end
 
   def limit_input!(env)
-    input = env[RACK_INPUT]
+    input = env['rack.input']
     klass = input.respond_to?(:rewind) ? RewindableWrapper : Wrapper
-    env[RACK_INPUT] = klass.new(input, @limit)
+    env['rack.input'] = klass.new(input, @limit)
   end
 
   # :startdoc:
diff --git a/lib/rainbows/process_client.rb b/lib/rainbows/process_client.rb
index f58770c..492b8a6 100644
--- a/lib/rainbows/process_client.rb
+++ b/lib/rainbows/process_client.rb
@@ -5,7 +5,6 @@ module Rainbows::ProcessClient
   include Rainbows::Const
 
   NULL_IO = Unicorn::HttpRequest::NULL_IO
-  RACK_INPUT = Unicorn::HttpRequest::RACK_INPUT
   IC = Unicorn::HttpRequest.input_class
   Rainbows.config!(self, :client_header_buffer_size, :keepalive_timeout)
 
@@ -39,13 +38,13 @@ module Rainbows::ProcessClient
       end
 
       set_input(env, hp)
-      env[REMOTE_ADDR] = kgio_addr
+      env['REMOTE_ADDR'] = kgio_addr
       hp.hijack_setup(env, to_io)
       status, headers, body = APP.call(env.merge!(RACK_DEFAULTS))
 
       if 100 == status.to_i
-        write(EXPECT_100_RESPONSE)
-        env.delete(HTTP_EXPECT)
+        write("HTTP/1.1 100 Continue\r\n\r\n".freeze)
+        env.delete('HTTP_EXPECT'.freeze)
         status, headers, body = APP.call(env)
       end
       return if hp.hijacked?
@@ -66,18 +65,18 @@ module Rainbows::ProcessClient
   end
 
   def set_input(env, hp)
-    env[RACK_INPUT] = 0 == hp.content_length ? NULL_IO : IC.new(self, hp)
+    env['rack.input'] = 0 == hp.content_length ? NULL_IO : IC.new(self, hp)
   end
 
   def process_pipeline(env, hp)
     begin
       set_input(env, hp)
-      env[REMOTE_ADDR] = kgio_addr
+      env['REMOTE_ADDR'] = kgio_addr
       hp.hijack_setup(env, to_io)
       status, headers, body = APP.call(env.merge!(RACK_DEFAULTS))
       if 100 == status.to_i
-        write(EXPECT_100_RESPONSE)
-        env.delete(HTTP_EXPECT)
+        write("HTTP/1.1 100 Continue\r\n\r\n".freeze)
+        env.delete('HTTP_EXPECT'.freeze)
         status, headers, body = APP.call(env)
       end
       return if hp.hijacked?
diff --git a/lib/rainbows/response.rb b/lib/rainbows/response.rb
index a661ab6..2e8d2d8 100644
--- a/lib/rainbows/response.rb
+++ b/lib/rainbows/response.rb
@@ -2,10 +2,6 @@
 # :enddoc:
 module Rainbows::Response
   include Unicorn::HttpResponse
-  Close = "close"
-  KeepAlive = "keep-alive"
-  Content_Length = "Content-Length".freeze
-  Transfer_Encoding = "Transfer-Encoding".freeze
   Rainbows.config!(self, :copy_stream)
 
   # private file class for IO objects opened by Rainbows! itself (and not
@@ -21,14 +17,12 @@ module Rainbows::Response
 
   # Rack 1.5.0 (protocol version 1.2) adds response hijacking support
   if ((Rack::VERSION[0] << 8) | Rack::VERSION[1]) >= 0x0102
-    RACK_HIJACK = "rack.hijack"
-
     def hijack_prepare(value)
       value
     end
 
     def hijack_socket
-      @hp.env[RACK_HIJACK].call
+      @hp.env['rack.hijack'].call
     end
   else
     def hijack_prepare(_)
@@ -62,7 +56,8 @@ module Rainbows::Response
         end
       end
     end
-    write(buf << "Connection: #{alive ? KeepAlive : Close}\r\n\r\n")
+    write(buf << "Connection: #{alive ? 'keep-alive'.freeze
+                                      : 'close'.freeze}\r\n\r\n")
 
     if hijack
       body = nil # ensure caller does not close body
@@ -152,22 +147,19 @@ module Rainbows::Response
   end  # ! COPY_STREAM
 
   if IO.method_defined?(:trysendfile) || COPY_STREAM
-    HTTP_RANGE = 'HTTP_RANGE'
-    Content_Range = 'Content-Range'.freeze
-
     # This does not support multipart responses (does anybody actually
     # use those?)
     def sendfile_range(status, headers)
       status = status.to_i
       if 206 == status
-        if %r{\Abytes (\d+)-(\d+)/\d+\z} =~ headers[Content_Range]
+        if %r{\Abytes (\d+)-(\d+)/\d+\z} =~ headers['Content-Range'.freeze]
           a, b = $1.to_i, $2.to_i
           return 206, headers, [ a,  b - a + 1 ]
         end
         return # wtf...
       end
       200 == status &&
-      /\Abytes=(\d+-\d*|\d*-\d+)\z/ =~ @hp.env[HTTP_RANGE] or
+      /\Abytes=(\d+-\d*|\d*-\d+)\z/ =~ @hp.env['HTTP_RANGE'] or
         return
       a, b = $1.split(/-/)
 
@@ -175,7 +167,7 @@ module Rainbows::Response
       # uses a regular Ruby Hash with properly-cased headers the
       # same way they're presented in rfc2616.
       headers = Rack::Utils::HeaderHash.new(headers) unless Hash === headers
-      clen = headers[Content_Length] or return
+      clen = headers['Content-Length'.freeze] or return
       size = clen.to_i
 
       if b.nil? # bytes=M-
@@ -190,13 +182,14 @@ module Rainbows::Response
       end
 
       if 0 > count || offset >= size
-        headers[Content_Length] = "0"
-        headers[Content_Range] = "bytes */#{clen}"
+        headers['Content-Length'.freeze] = "0"
+        headers['Content-Range'.freeze] = "bytes */#{clen}"
         return 416, headers, nil
       else
         count = size if count > size
-        headers[Content_Length] = count.to_s
-        headers[Content_Range] = "bytes #{offset}-#{offset+count-1}/#{clen}"
+        headers['Content-Length'.freeze] = count.to_s
+        headers['Content-Range'.freeze] =
+                                    "bytes #{offset}-#{offset+count-1}/#{clen}"
         return 206, headers, [ offset, count ]
       end
     end
diff --git a/lib/rainbows/reverse_proxy.rb b/lib/rainbows/reverse_proxy.rb
index c1f1dc2..16a6f65 100644
--- a/lib/rainbows/reverse_proxy.rb
+++ b/lib/rainbows/reverse_proxy.rb
@@ -47,15 +47,6 @@ class Rainbows::ReverseProxy
   autoload :EventMachine, 'rainbows/reverse_proxy/event_machine'
   autoload :EvClient, 'rainbows/reverse_proxy/ev_client'
 
-  HTTP_X_FORWARDED_FOR = "HTTP_X_FORWARDED_FOR"
-  REMOTE_ADDR = "REMOTE_ADDR"
-  REQUEST_METHOD = "REQUEST_METHOD"
-  REQUEST_URI = "REQUEST_URI"
-  CRLF = "\r\n"
-  TR = %w(_ -)
-  CONTENT_LENGTH = "CONTENT_LENGTH"
-  HTTP_TRANSFER_ENCODING = "HTTP_TRANSFER_ENCODING"
-  RackInput = "rack.input"
   E502 = [ 502, [ %w(Content-Length 0), %w(Content-Type text/plain) ], [] ]
 
   def initialize(opts)
@@ -113,24 +104,23 @@ class Rainbows::ReverseProxy
 
   # returns request headers for sending to the upstream as a string
   def build_headers(env, input)
-    remote_addr = env[REMOTE_ADDR]
-    xff = env[HTTP_X_FORWARDED_FOR]
+    remote_addr = env['REMOTE_ADDR']
+    xff = env['HTTP_X_FORWARDED_FOR']
     xff = xff ? "#{xff},#{remote_addr}" : remote_addr
-    req = "#{env[REQUEST_METHOD]} #{env[REQUEST_URI]} HTTP/1.0\r\n" \
+    req = "#{env['REQUEST_METHOD']} #{env['REQUEST_URI']} HTTP/1.0\r\n" \
           "Connection: close\r\n" \
           "X-Forwarded-For: #{xff}\r\n"
-    uscore, dash = *TR
     env.each do |key, value|
       %r{\AHTTP_(\w+)\z} =~ key or next
       key = $1
       next if %r{\A(?:VERSION|CONNECTION|KEEP_ALIVE|X_FORWARDED_FOR)\z}x =~ key
-      key.tr!(uscore, dash)
+      key.tr!('_'.freeze, '-'.freeze)
       req << "#{key}: #{value}\r\n"
     end
     input and req << (input.respond_to?(:size) ?
                      "Content-Length: #{input.size}\r\n" :
-                     "Transfer-Encoding: chunked\r\n")
-    req << CRLF
+                     "Transfer-Encoding: chunked\r\n".freeze)
+    req << "\r\n".freeze
   end
 
   def pick_upstream(env) # +env+ is reserved for future expansion
@@ -139,16 +129,16 @@ class Rainbows::ReverseProxy
   end
 
   def prepare_input!(env)
-    if cl = env[CONTENT_LENGTH]
+    if cl = env['CONTENT_LENGTH']
       size = cl.to_i
       size > 0 or return
-    elsif %r{\Achunked\z}i =~ env.delete(HTTP_TRANSFER_ENCODING)
+    elsif %r{\Achunked\z}i =~ env.delete('HTTP_TRANSFER_ENCODING')
       # do people use multiple transfer-encodings?
     else
       return
     end
 
-    input = env[RackInput]
+    input = env['rack.input']
     if input.respond_to?(:rewind)
       if input.respond_to?(:size)
         input.size # TeeInput-specific behavior
diff --git a/lib/rainbows/reverse_proxy/ev_client.rb b/lib/rainbows/reverse_proxy/ev_client.rb
index cf97c4d..ab3f7a3 100644
--- a/lib/rainbows/reverse_proxy/ev_client.rb
+++ b/lib/rainbows/reverse_proxy/ev_client.rb
@@ -3,18 +3,15 @@
 require 'tempfile'
 module Rainbows::ReverseProxy::EvClient
   include Rainbows::ReverseProxy::Synchronous
-  AsyncCallback = "async.callback"
   CBB = Unicorn::TeeInput.client_body_buffer_size
-  Content_Length = "Content-Length"
-  Transfer_Encoding = "Transfer-Encoding"
 
   def receive_data(buf)
     if @body
       @body << buf
     else
       response = @parser.headers(@headers, @rbuf << buf) or return
-      if (cl = @headers[Content_Length] && cl.to_i > CBB) ||
-         (%r{\bchunked\b} =~ @headers[Transfer_Encoding])
+      if (cl = @headers['Content-Length'.freeze] && cl.to_i > CBB) ||
+         (%r{\bchunked\b} =~ @headers['Transfer-Encoding'.freeze])
         @body = LargeBody.new("")
         @body << @rbuf
         @response = response << @body
diff --git a/lib/rainbows/sendfile.rb b/lib/rainbows/sendfile.rb
index 767c0f9..59906e2 100644
--- a/lib/rainbows/sendfile.rb
+++ b/lib/rainbows/sendfile.rb
@@ -52,12 +52,10 @@ class Rainbows::Sendfile < Struct.new(:app)
   # +each+ in case a given concurrency model does not optimize
   # +to_path+ calls.
   class Body < Struct.new(:to_path) # :nodoc: all
-    CONTENT_LENGTH = 'Content-Length'.freeze
-
     def self.new(path, headers)
-      unless headers[CONTENT_LENGTH]
+      unless headers['Content-Length'.freeze]
         stat = File.stat(path)
-        headers[CONTENT_LENGTH] = stat.size.to_s if stat.file?
+        headers['Content-Length'.freeze] = stat.size.to_s if stat.file?
       end
       super(path)
     end
@@ -71,14 +69,10 @@ class Rainbows::Sendfile < Struct.new(:app)
     end
   end
 
-  # :stopdoc:
-  X_SENDFILE = 'X-Sendfile'
-  # :startdoc:
-
   def call(env) # :nodoc:
     status, headers, body = app.call(env)
     headers = Rack::Utils::HeaderHash.new(headers) unless Hash === headers
-    if path = headers.delete(X_SENDFILE)
+    if path = headers.delete('X-Sendfile'.freeze)
       body = Body.new(path, headers) unless body.respond_to?(:to_path)
     end
     [ status, headers, body ]
diff --git a/lib/rainbows/server_token.rb b/lib/rainbows/server_token.rb
index 0ee87ac..09897d4 100644
--- a/lib/rainbows/server_token.rb
+++ b/lib/rainbows/server_token.rb
@@ -19,11 +19,6 @@ module Rainbows
 
 class ServerToken < Struct.new(:app, :token)
 
-  # :stopdoc:
-  #
-  # Freeze constants as they're slightly faster when setting hashes
-  SERVER = "Server".freeze
-
   def initialize(app, token = Const::RACK_DEFAULTS['SERVER_SOFTWARE'])
     super
   end
@@ -31,7 +26,7 @@ class ServerToken < Struct.new(:app, :token)
   def call(env)
     status, headers, body = app.call(env)
     headers = Rack::Utils::HeaderHash.new(headers) unless Hash === headers
-    headers[SERVER] = token
+    headers['Server'.freeze] = token
     [ status, headers, body ]
   end
   # :startdoc:
diff --git a/lib/rainbows/stream_response_epoll.rb b/lib/rainbows/stream_response_epoll.rb
index 1f32dcc..c36acaf 100644
--- a/lib/rainbows/stream_response_epoll.rb
+++ b/lib/rainbows/stream_response_epoll.rb
@@ -20,7 +20,6 @@ require "raindrops"
 # * sleepy_penguin 3.0.1 or later
 module Rainbows::StreamResponseEpoll
   # :stopdoc:
-  HEADER_END = "X-Accel-Buffering: no\r\n\r\n"
   autoload :Client, "rainbows/stream_response_epoll/client"
 
   def http_response_write(socket, status, headers, body)
@@ -46,7 +45,7 @@ module Rainbows::StreamResponseEpoll
           end
         end
       end
-      buf << HEADER_END
+      buf << "X-Accel-Buffering: no\r\n\r\n".freeze
 
       case rv = socket.kgio_trywrite(buf)
       when nil then break
@@ -101,8 +100,8 @@ module Rainbows::StreamResponseEpoll
     status, headers, body = @app.call(env = @request.read(client))
 
     if 100 == status.to_i
-      client.write(Unicorn::Const::EXPECT_100_RESPONSE)
-      env.delete(Unicorn::Const::HTTP_EXPECT)
+      client.write("HTTP/1.1 100 Continue\r\n\r\n".freeze)
+      env.delete('HTTP_EXPECT'.freeze)
       status, headers, body = @app.call(env)
     end
     @request.headers? or headers = nil
-- 
EW


^ permalink raw reply	[flat|threaded] 6+ messages in thread

* [PATCH 5/5] http_parser: workaround hijack changes in unicorn 5
  2015-11-14  2:47 [WIP 0/5] updates for unicorn 5 internal changes Eric Wong
                   ` (3 preceding siblings ...)
  2015-11-14  2:47 ` [PATCH 4/5] reduce constant lookup dependencies Eric Wong
@ 2015-11-14  2:47 ` Eric Wong
  4 siblings, 0 replies; 6+ messages in thread
From: Eric Wong @ 2015-11-14  2:47 UTC (permalink / raw)
  To: rainbows-public

unicorn lost the hijack_setup method in version 5,
so we must recreate it ourselves.
---
 lib/rainbows/coolio/client.rb        |  2 +-
 lib/rainbows/coolio/thread_client.rb |  2 +-
 lib/rainbows/epoll/client.rb         |  2 +-
 lib/rainbows/event_machine/client.rb |  2 +-
 lib/rainbows/http_parser.rb          |  9 +++++++++
 lib/rainbows/process_client.rb       |  4 ++--
 lib/rainbows/response.rb             | 16 +++-------------
 7 files changed, 18 insertions(+), 19 deletions(-)

diff --git a/lib/rainbows/coolio/client.rb b/lib/rainbows/coolio/client.rb
index c05fd3a..ad827f6 100644
--- a/lib/rainbows/coolio/client.rb
+++ b/lib/rainbows/coolio/client.rb
@@ -125,7 +125,7 @@ class Rainbows::Coolio::Client < Coolio::IO
     @env['rack.input'] = input
     @env['REMOTE_ADDR'] = @_io.kgio_addr
     @env['async.callback'] = method(:write_async_response)
-    @hp.hijack_setup(@env, @_io)
+    @hp.hijack_setup(@_io)
     status, headers, body = catch(:async) {
       APP.call(@env.merge!(RACK_DEFAULTS))
     }
diff --git a/lib/rainbows/coolio/thread_client.rb b/lib/rainbows/coolio/thread_client.rb
index 4de705f..a3a2ebf 100644
--- a/lib/rainbows/coolio/thread_client.rb
+++ b/lib/rainbows/coolio/thread_client.rb
@@ -26,7 +26,7 @@ class Rainbows::Coolio::ThreadClient < Rainbows::Coolio::Client
   def app_response
     begin
       @env['REMOTE_ADDR'] = @_io.kgio_addr
-      @hp.hijack_setup(@env, @_io)
+      @hp.hijack_setup(@_io)
       APP.call(@env.merge!(RACK_DEFAULTS))
     rescue => e
       Rainbows::Error.app(e) # we guarantee this does not raise
diff --git a/lib/rainbows/epoll/client.rb b/lib/rainbows/epoll/client.rb
index 2d95a99..6dcbb81 100644
--- a/lib/rainbows/epoll/client.rb
+++ b/lib/rainbows/epoll/client.rb
@@ -65,7 +65,7 @@ module Rainbows::Epoll::Client
   def app_call input # called by on_read()
     @env['rack.input'] = input
     @env['REMOTE_ADDR'] = kgio_addr
-    @hp.hijack_setup(@env, self)
+    @hp.hijack_setup(self)
     status, headers, body = APP.call(@env.merge!(RACK_DEFAULTS))
     return hijacked if @hp.hijacked?
     ev_write_response(status, headers, body, @hp.next?)
diff --git a/lib/rainbows/event_machine/client.rb b/lib/rainbows/event_machine/client.rb
index 7fb88f6..039b7a6 100644
--- a/lib/rainbows/event_machine/client.rb
+++ b/lib/rainbows/event_machine/client.rb
@@ -38,7 +38,7 @@ class Rainbows::EventMachine::Client < EM::Connection
     @env['REMOTE_ADDR'] = @_io.kgio_addr
     @env['async.callback'] = method(:write_async_response)
     @env['async.close'] = EM::DefaultDeferrable.new
-    @hp.hijack_setup(@env, @_io)
+    @hp.hijack_setup(@_io)
     status, headers, body = catch(:async) {
       APP.call(@env.merge!(RACK_DEFAULTS))
     }
diff --git a/lib/rainbows/http_parser.rb b/lib/rainbows/http_parser.rb
index 30a67cb..bcf1dba 100644
--- a/lib/rainbows/http_parser.rb
+++ b/lib/rainbows/http_parser.rb
@@ -17,6 +17,15 @@ class Rainbows::HttpParser < Unicorn::HttpParser
     super
   end
 
+  def hijack_setup(io)
+    @hijack_io = io
+    env['rack.hijack'] = self # avoid allocating a new proc this way
+  end
+
+  def call # for rack.hijack
+    env['rack.hijack_io'] = @hijack_io
+  end
+
   def self.quit
     alias_method :next?, :never!
   end
diff --git a/lib/rainbows/process_client.rb b/lib/rainbows/process_client.rb
index 492b8a6..a39d6cd 100644
--- a/lib/rainbows/process_client.rb
+++ b/lib/rainbows/process_client.rb
@@ -39,7 +39,7 @@ module Rainbows::ProcessClient
 
       set_input(env, hp)
       env['REMOTE_ADDR'] = kgio_addr
-      hp.hijack_setup(env, to_io)
+      hp.hijack_setup(to_io)
       status, headers, body = APP.call(env.merge!(RACK_DEFAULTS))
 
       if 100 == status.to_i
@@ -72,7 +72,7 @@ module Rainbows::ProcessClient
     begin
       set_input(env, hp)
       env['REMOTE_ADDR'] = kgio_addr
-      hp.hijack_setup(env, to_io)
+      hp.hijack_setup(to_io)
       status, headers, body = APP.call(env.merge!(RACK_DEFAULTS))
       if 100 == status.to_i
         write("HTTP/1.1 100 Continue\r\n\r\n".freeze)
diff --git a/lib/rainbows/response.rb b/lib/rainbows/response.rb
index 2e8d2d8..0b5e542 100644
--- a/lib/rainbows/response.rb
+++ b/lib/rainbows/response.rb
@@ -15,18 +15,8 @@ module Rainbows::Response
       Rainbows::HttpParser.keepalive_requests = 0
   end
 
-  # Rack 1.5.0 (protocol version 1.2) adds response hijacking support
-  if ((Rack::VERSION[0] << 8) | Rack::VERSION[1]) >= 0x0102
-    def hijack_prepare(value)
-      value
-    end
-
-    def hijack_socket
-      @hp.env['rack.hijack'].call
-    end
-  else
-    def hijack_prepare(_)
-    end
+  def hijack_socket
+    @hp.env['rack.hijack'].call
   end
 
   # returns the original body on success
@@ -45,7 +35,7 @@ module Rainbows::Response
       when "rack.hijack"
         # this was an illegal key in Rack < 1.5, so it should be
         # OK to silently discard it for those older versions
-        hijack = hijack_prepare(value)
+        hijack = value
         alive = false # No persistent connections for hijacking
       else
         if /\n/ =~ value
-- 
EW


^ permalink raw reply	[flat|threaded] 6+ messages in thread

end of thread, back to index

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-11-14  2:47 [WIP 0/5] updates for unicorn 5 internal changes Eric Wong
2015-11-14  2:47 ` [PATCH 1/5] http_parser: handle keepalive_requests internally Eric Wong
2015-11-14  2:47 ` [PATCH 2/5] kill the moronic Status: header Eric Wong
2015-11-14  2:47 ` [PATCH 3/5] reflect changes in Rack::Utils::HTTP_STATUS_CODES Eric Wong
2015-11-14  2:47 ` [PATCH 4/5] reduce constant lookup dependencies Eric Wong
2015-11-14  2:47 ` [PATCH 5/5] http_parser: workaround hijack changes in unicorn 5 Eric Wong

Rainbows! Rack HTTP server user/dev discussion

Archives are clonable:
	git clone --mirror http://bogomips.org/rainbows-public
	git clone --mirror http://ou63pmih66umazou.onion/rainbows-public

Newsgroups are available over NNTP:
	nntp://news.public-inbox.org/inbox.comp.lang.ruby.rainbows
	nntp://ou63pmih66umazou.onion/inbox.comp.lang.ruby.rainbows

 note: .onion URLs require Tor: https://www.torproject.org/
       or Tor2web: https://www.tor2web.org/

AGPL code for this site: git clone https://public-inbox.org/ public-inbox