Rainbows! Rack HTTP server user/dev discussion
 help / color / mirror / code / Atom feed
Search results ordered by [date|relevance]  view[summary|nested|Atom feed]
thread overview below | download mbox.gz: |
* [ANN] Rainbows! 5.0.0 - Rack HTTP server for the sleepy
@ 2015-11-25  1:04  5% Eric Wong
  0 siblings, 0 replies; 3+ results
From: Eric Wong @ 2015-11-25  1:04 UTC (permalink / raw)
  To: ruby-talk; +Cc: rainbows-public

Rainbows! is an HTTP server for sleepy Rack applications.
While it will be maintained as long as anybody uses it,
use of Rainbows! for new projects is not recommended,
try other servers instead:

    http://bogomips.org/rainbows-public/20151020095934.GA19114@dcvr.yhbt.net/

Rainbows! 5.0.0 - maintained as long as anybody uses it!

This release syncs with unicorn 5 and drops some old compatibility
cruft from old releases.  Performance should be roughly unchanged
for Ruby 2.2 users while older Rubies (1.9.3 - 2.1) will see
minor, probably unnoticeable performance regressions.

Compatibility:

* The horrible, proprietary (:P) "Status:" response header is
  finally gone, saving at least 16 precious bytes in every HTTP
  response.  This should make it easier to write custom HTTP clients
  which are compatible across all HTTP servers.  It will hopefully
  make migrating between different Rack servers easier for new
  projects.

* Ruby 1.8 support removed.  Ruby 1.9.3 is currently the earliest
  supported version.  However, expect minor, likely-unnoticeable
  performance regressions if you use Ruby 2.1 or earlier.  Going
  forward, Rainbows! will favor the latest version (currently 2.2) of
  the mainline Ruby implementation, potentially sacrificing
  performance on older Rubies.

New features:

* sd_listen_fds(3) emulation added for systemd compatibility.
  You may now stop using PID files and other process monitoring
  software when using systemd.

* Newly-set TCP socket options are now applied to inherited sockets.

* Dynamic changes in the application to Rack::Utils::HTTP_STATUS
  hash is now supported; allowing users to set custom status lines
  in Rack to be reflected in unicorn.  This feature causes a minor
  performance regression, but is made up for Ruby 2.2 users with
  other optimizations.

* The monotonic clock is used under Ruby 2.1+, making the
  timeout feature immune to system clock changes.

As Rainbows! may be used anonymously without registration, the
project is committed to supporting anonymous and pseudonymous
help requests, contributions and feedback via plain-text mail to:

    rainbows-public@bogomips.org

The mail submission port (587) is open to those behind firewalls
and allows access via Tor and anonymous remailers.
Archives are accessible via:

* http://bogomips.org/rainbows-public/
* nntp://news.public-inbox.org/inbox.comp.lang.ruby.rainbows
* nntp://news.gmane.org/gmane.comp.lang.ruby.rainbows.general

and mirrored to various other places, so you do not even need
to use a valid address when posting.

18 changes since Rainbows! 4.7.0

      README: remove Zbatery references
      http_parser: handle keepalive_requests internally
      kill the moronic Status: header
      reflect changes in Rack::Utils::HTTP_STATUS_CODES
      reduce constant lookup dependencies
      http_parser: workaround hijack changes in unicorn 5
      http_server: add master_pid attribute
      stream_response_epoll: remove hijack_prepare call
      bump to unicorn 5.0.1, use monotonic clock
      add .gitattributes for Ruby method detection
      response: avoid garbage string entirely
      tiny bytecode reductions for cold paths
      Ruby 1.9.3+-only cleanups
      revactor: remove fcntl dependency
      response: simplify regexp
      t0105: fix test reliability
      fix Rainbows.now definition for old Rubies
      fix broken constant lookups in unmaintained bits

* http://rainbows.bogomips.org/
* rainbows-public@bogomips.org
* http://bogomips.org/rainbows-public/
* git clone git://bogomips.org/rainbows.git
* http://rainbows.bogomips.org/NEWS.atom.xml

*zzzzzzzz*

^ permalink raw reply	[relevance 5%]

* [PATCH 4/5] reduce constant lookup dependencies
  2015-11-14  2:47  7% [WIP 0/5] updates for unicorn 5 internal changes Eric Wong
@ 2015-11-14  2:47  2% ` Eric Wong
  0 siblings, 0 replies; 3+ results
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 related	[relevance 2%]

* [WIP 0/5] updates for unicorn 5 internal changes
@ 2015-11-14  2:47  7% Eric Wong
  2015-11-14  2:47  2% ` [PATCH 4/5] reduce constant lookup dependencies Eric Wong
  0 siblings, 1 reply; 3+ results
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	[relevance 7%]

Results 1-3 of 3 | reverse | options above
-- pct% links below jump to the message on this page, permalinks otherwise --
2015-11-14  2:47  7% [WIP 0/5] updates for unicorn 5 internal changes Eric Wong
2015-11-14  2:47  2% ` [PATCH 4/5] reduce constant lookup dependencies Eric Wong
2015-11-25  1:04  5% [ANN] Rainbows! 5.0.0 - Rack HTTP server for the sleepy Eric Wong

Code repositories for project(s) associated with this public inbox

	https://yhbt.net/rainbows.git/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).