Rainbows! Rack HTTP server user/dev discussion
 help / Atom feed
From: Eric Wong <e@80x24.org>
To: rainbows-public@bogomips.org
Subject: [PATCH 4/5] reduce constant lookup dependencies
Date: Sat, 14 Nov 2015 02:47:24 +0000
Message-ID: <20151114024725.24139-5-e@80x24.org> (raw)
In-Reply-To: <20151114024725.24139-1-e@80x24.org>

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


  parent reply index

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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 ` Eric Wong [this message]
2015-11-14  2:47 ` [PATCH 5/5] http_parser: workaround hijack changes in unicorn 5 Eric Wong

Reply instructions:

You may reply publically to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://bogomips.org/rainbows/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20151114024725.24139-5-e@80x24.org \
    --to=e@80x24.org \
    --cc=rainbows-public@bogomips.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

Rainbows! Rack HTTP server user/dev discussion

Archives are clonable:
	git clone --mirror https://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