* [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).