* [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 related [flat|nested] 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 related [flat|nested] 6+ messages in thread