rainbows 4.7.0 → 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/.gitattributes +5 -0
  3. data/GIT-VERSION-GEN +1 -1
  4. data/README +5 -9
  5. data/bin/rainbows +3 -3
  6. data/lib/rainbows.rb +18 -6
  7. data/lib/rainbows/configurator.rb +8 -8
  8. data/lib/rainbows/const.rb +0 -3
  9. data/lib/rainbows/coolio.rb +2 -7
  10. data/lib/rainbows/coolio/client.rb +6 -6
  11. data/lib/rainbows/coolio/heartbeat.rb +2 -2
  12. data/lib/rainbows/coolio/thread_client.rb +3 -3
  13. data/lib/rainbows/dev_fd_response.rb +8 -14
  14. data/lib/rainbows/epoll/client.rb +9 -10
  15. data/lib/rainbows/error.rb +2 -2
  16. data/lib/rainbows/ev_core.rb +11 -17
  17. data/lib/rainbows/event_machine/client.rb +7 -7
  18. data/lib/rainbows/event_machine/try_defer.rb +1 -4
  19. data/lib/rainbows/fiber.rb +1 -1
  20. data/lib/rainbows/fiber/base.rb +3 -3
  21. data/lib/rainbows/fiber/coolio/heartbeat.rb +1 -1
  22. data/lib/rainbows/fiber/io.rb +1 -1
  23. data/lib/rainbows/http_parser.rb +24 -0
  24. data/lib/rainbows/http_server.rb +5 -4
  25. data/lib/rainbows/join_threads.rb +2 -2
  26. data/lib/rainbows/max_body.rb +4 -9
  27. data/lib/rainbows/process_client.rb +11 -12
  28. data/lib/rainbows/response.rb +20 -37
  29. data/lib/rainbows/revactor.rb +0 -1
  30. data/lib/rainbows/revactor/client.rb +2 -3
  31. data/lib/rainbows/revactor/proxy.rb +1 -1
  32. data/lib/rainbows/reverse_proxy.rb +9 -19
  33. data/lib/rainbows/reverse_proxy/coolio.rb +3 -3
  34. data/lib/rainbows/reverse_proxy/ev_client.rb +2 -5
  35. data/lib/rainbows/reverse_proxy/event_machine.rb +1 -1
  36. data/lib/rainbows/sendfile.rb +3 -9
  37. data/lib/rainbows/server_token.rb +1 -6
  38. data/lib/rainbows/stream_response_epoll.rb +8 -9
  39. data/lib/rainbows/thread_timeout.rb +4 -4
  40. data/lib/rainbows/writer_thread_pool.rb +2 -2
  41. data/lib/rainbows/xepoll_thread_pool/client.rb +3 -4
  42. data/lib/rainbows/xepoll_thread_spawn/client.rb +3 -4
  43. data/rainbows.gemspec +1 -1
  44. data/t/t0105-rack-input-limit-bigger.sh +10 -2
  45. data/t/test_isolate.rb +1 -1
  46. metadata +5 -4
@@ -32,20 +32,20 @@ def on_readable
32
32
  when :wait_readable
33
33
  return
34
34
  when nil
35
- @env[AsyncCallback].call(@response)
35
+ @env['async.callback'].call(@response)
36
36
  return close
37
37
  end while true # we always read until EAGAIN or EOF
38
38
 
39
39
  rescue => e
40
40
  case e
41
41
  when Errno::ECONNRESET
42
- @env[AsyncCallback].call(@response)
42
+ @env['async.callback'].call(@response)
43
43
  return close
44
44
  when SystemCallError
45
45
  else
46
46
  Unicorn.log_error(@env["rack.logger"], "on_readable", e)
47
47
  end
48
- @env[AsyncCallback].call(Rainbows::ReverseProxy::E502)
48
+ @env['async.callback'].call(Rainbows::ReverseProxy::E502)
49
49
  close
50
50
  end
51
51
  end
@@ -3,18 +3,15 @@
3
3
  require 'tempfile'
4
4
  module Rainbows::ReverseProxy::EvClient
5
5
  include Rainbows::ReverseProxy::Synchronous
6
- AsyncCallback = "async.callback"
7
6
  CBB = Unicorn::TeeInput.client_body_buffer_size
8
- Content_Length = "Content-Length"
9
- Transfer_Encoding = "Transfer-Encoding"
10
7
 
11
8
  def receive_data(buf)
12
9
  if @body
13
10
  @body << buf
14
11
  else
15
12
  response = @parser.headers(@headers, @rbuf << buf) or return
16
- if (cl = @headers[Content_Length] && cl.to_i > CBB) ||
17
- (%r{\bchunked\b} =~ @headers[Transfer_Encoding])
13
+ if (cl = @headers['Content-Length'.freeze] && cl.to_i > CBB) ||
14
+ (%r{\bchunked\b} =~ @headers['Transfer-Encoding'.freeze])
18
15
  @body = LargeBody.new("")
19
16
  @body << @rbuf
20
17
  @response = response << @body
@@ -30,7 +30,7 @@ def on_write_complete
30
30
  end
31
31
 
32
32
  def unbind
33
- @env[AsyncCallback].call(@response || Rainbows::ReverseProxy::E502)
33
+ @env['async.callback'].call(@response || Rainbows::ReverseProxy::E502)
34
34
  end
35
35
  end
36
36
 
@@ -52,12 +52,10 @@ class Rainbows::Sendfile < Struct.new(:app)
52
52
  # +each+ in case a given concurrency model does not optimize
53
53
  # +to_path+ calls.
54
54
  class Body < Struct.new(:to_path) # :nodoc: all
55
- CONTENT_LENGTH = 'Content-Length'.freeze
56
-
57
55
  def self.new(path, headers)
58
- unless headers[CONTENT_LENGTH]
56
+ unless headers['Content-Length'.freeze]
59
57
  stat = File.stat(path)
60
- headers[CONTENT_LENGTH] = stat.size.to_s if stat.file?
58
+ headers['Content-Length'.freeze] = stat.size.to_s if stat.file?
61
59
  end
62
60
  super(path)
63
61
  end
@@ -71,14 +69,10 @@ def each
71
69
  end
72
70
  end
73
71
 
74
- # :stopdoc:
75
- X_SENDFILE = 'X-Sendfile'
76
- # :startdoc:
77
-
78
72
  def call(env) # :nodoc:
79
73
  status, headers, body = app.call(env)
80
74
  headers = Rack::Utils::HeaderHash.new(headers) unless Hash === headers
81
- if path = headers.delete(X_SENDFILE)
75
+ if path = headers.delete('X-Sendfile'.freeze)
82
76
  body = Body.new(path, headers) unless body.respond_to?(:to_path)
83
77
  end
84
78
  [ status, headers, body ]
@@ -19,11 +19,6 @@ module Rainbows
19
19
 
20
20
  class ServerToken < Struct.new(:app, :token)
21
21
 
22
- # :stopdoc:
23
- #
24
- # Freeze constants as they're slightly faster when setting hashes
25
- SERVER = "Server".freeze
26
-
27
22
  def initialize(app, token = Const::RACK_DEFAULTS['SERVER_SOFTWARE'])
28
23
  super
29
24
  end
@@ -31,7 +26,7 @@ def initialize(app, token = Const::RACK_DEFAULTS['SERVER_SOFTWARE'])
31
26
  def call(env)
32
27
  status, headers, body = app.call(env)
33
28
  headers = Rack::Utils::HeaderHash.new(headers) unless Hash === headers
34
- headers[SERVER] = token
29
+ headers['Server'.freeze] = token
35
30
  [ status, headers, body ]
36
31
  end
37
32
  # :startdoc:
@@ -20,33 +20,32 @@
20
20
  # * sleepy_penguin 3.0.1 or later
21
21
  module Rainbows::StreamResponseEpoll
22
22
  # :stopdoc:
23
- CODES = Unicorn::HttpResponse::CODES
24
- HEADER_END = "X-Accel-Buffering: no\r\n\r\n"
25
23
  autoload :Client, "rainbows/stream_response_epoll/client"
26
24
 
27
25
  def http_response_write(socket, status, headers, body)
28
- status = CODES[status.to_i] || status
29
26
  hijack = ep_client = false
30
27
 
31
28
  if headers
32
29
  # don't set extra headers here, this is only intended for
33
30
  # consuming by nginx.
34
- buf = "HTTP/1.0 #{status}\r\nStatus: #{status}\r\n"
31
+ code = status.to_i
32
+ msg = Rack::Utils::HTTP_STATUS_CODES[code]
33
+ buf = "HTTP/1.0 #{msg ? %Q(#{code} #{msg}) : status}\r\n"
35
34
  headers.each do |key, value|
36
35
  case key
37
36
  when "rack.hijack"
38
- hijack = hijack_prepare(value)
37
+ hijack = value
39
38
  body = nil # ensure we do not close body
40
39
  else
41
40
  if /\n/ =~ value
42
41
  # avoiding blank, key-only cookies with /\n+/
43
- buf << value.split(/\n+/).map! { |v| "#{key}: #{v}\r\n" }.join
42
+ value.split(/\n+/).each { |v| buf << "#{key}: #{v}\r\n" }
44
43
  else
45
44
  buf << "#{key}: #{value}\r\n"
46
45
  end
47
46
  end
48
47
  end
49
- buf << HEADER_END
48
+ buf << "X-Accel-Buffering: no\r\n\r\n".freeze
50
49
 
51
50
  case rv = socket.kgio_trywrite(buf)
52
51
  when nil then break
@@ -101,8 +100,8 @@ def process_client(client)
101
100
  status, headers, body = @app.call(env = @request.read(client))
102
101
 
103
102
  if 100 == status.to_i
104
- client.write(Unicorn::Const::EXPECT_100_RESPONSE)
105
- env.delete(Unicorn::Const::HTTP_EXPECT)
103
+ client.write("HTTP/1.1 100 Continue\r\n\r\n".freeze)
104
+ env.delete('HTTP_EXPECT'.freeze)
106
105
  status, headers, body = @app.call(env)
107
106
  end
108
107
  @request.headers? or headers = nil
@@ -63,7 +63,7 @@ class Rainbows::ThreadTimeout
63
63
 
64
64
  # The MRI 1.8 won't be usable in January 2038, we'll raise this
65
65
  # when we eventually drop support for 1.8 (before 2038, hopefully)
66
- NEVER = Time.at(0x7fffffff)
66
+ NEVER = 0x7fffffff
67
67
 
68
68
  def initialize(app, opts)
69
69
  # @timeout must be Numeric since we add this to Time
@@ -114,7 +114,7 @@ def call(env)
114
114
  # is hopeless and we might as well just die anyways.
115
115
  # initialize guarantees @timeout will be Numeric
116
116
  start_watchdog(env) unless @watchdog
117
- @active[Thread.current] = Time.now + @timeout
117
+ @active[Thread.current] = Rainbows.now + @timeout
118
118
 
119
119
  begin
120
120
  # It is important to unlock inside this begin block
@@ -162,7 +162,7 @@ def start_watchdog(env)
162
162
  # that are about to release themselves from the eye of the
163
163
  # watchdog thread.
164
164
  @lock.synchronize do
165
- now = Time.now
165
+ now = Rainbows.now
166
166
  @active.delete_if do |thread, expire_at|
167
167
  # We also use this loop to get the maximum possible time to
168
168
  # sleep for if we're not killing the thread.
@@ -184,7 +184,7 @@ def start_watchdog(env)
184
184
  sleep(@timeout)
185
185
  else
186
186
  # sleep until the next known thread is about to expire.
187
- sec = next_expiry - Time.now
187
+ sec = next_expiry - Rainbows.now
188
188
  sec > 0.0 ? sleep(sec) : Thread.pass # give other threads a chance
189
189
  end
190
190
  rescue => e
@@ -50,9 +50,9 @@ def worker_loop(worker) # :nodoc:
50
50
  end
51
51
  end
52
52
 
53
- @@q = qp.map { |q| q.queue }
53
+ @@q = qp.map(&:queue)
54
54
  super(worker) # accept loop from Unicorn
55
- qp.each { |q| q.quit! }
55
+ qp.each(&:quit!)
56
56
  end
57
57
  # :startdoc:
58
58
  end
@@ -38,15 +38,14 @@ def self.app_run(queue)
38
38
  ep = SleepyPenguin::Epoll
39
39
  EP = ep.new
40
40
  IN = ep::IN | ep::ONESHOT
41
- KATO = {}
42
- KATO.compare_by_identity if KATO.respond_to?(:compare_by_identity)
41
+ KATO = {}.compare_by_identity
43
42
  LOCK = Mutex.new
44
43
  Rainbows.at_quit do
45
44
  clients = nil
46
45
  LOCK.synchronize { clients = KATO.keys; KATO.clear }
47
46
  clients.each { |io| io.closed? or io.close }
48
47
  end
49
- @@last_expire = Time.now
48
+ @@last_expire = Rainbows.now
50
49
 
51
50
  def kato_set
52
51
  LOCK.synchronize { KATO[self] = @@last_expire }
@@ -70,7 +69,7 @@ def self.loop
70
69
  end
71
70
 
72
71
  def self.expire
73
- return if ((now = Time.now) - @@last_expire) < 1.0
72
+ return if ((now = Rainbows.now) - @@last_expire) < 1.0
74
73
  if (ot = KEEPALIVE_TIMEOUT) >= 0
75
74
  ot = now - ot
76
75
  defer = []
@@ -27,15 +27,14 @@ def self.included(klass) # included in Rainbows::Client
27
27
  ep = SleepyPenguin::Epoll
28
28
  EP = ep.new
29
29
  IN = ep::IN | ep::ONESHOT
30
- KATO = {}
31
- KATO.compare_by_identity if KATO.respond_to?(:compare_by_identity)
30
+ KATO = {}.compare_by_identity
32
31
  LOCK = Mutex.new
33
32
  Rainbows.at_quit do
34
33
  clients = nil
35
34
  LOCK.synchronize { clients = KATO.keys; KATO.clear }
36
35
  clients.each { |io| io.closed? or io.shutdown }
37
36
  end
38
- @@last_expire = Time.now
37
+ @@last_expire = Rainbows.now
39
38
 
40
39
  def kato_set
41
40
  LOCK.synchronize { KATO[self] = @@last_expire }
@@ -59,7 +58,7 @@ def self.loop
59
58
  end
60
59
 
61
60
  def self.expire
62
- return if ((now = Time.now) - @@last_expire) < 1.0
61
+ return if ((now = Rainbows.now) - @@last_expire) < 1.0
63
62
  if (ot = KEEPALIVE_TIMEOUT) >= 0
64
63
  ot = now - ot
65
64
  defer = []
@@ -27,7 +27,7 @@
27
27
  # we need unicorn for the HTTP parser and process management
28
28
  # we need unicorn 4.8.0+ since we depend on undocumented/unsupported
29
29
  # unicorn internals.
30
- s.add_dependency(%q<unicorn>, ["~> 4.8"])
30
+ s.add_dependency(%q<unicorn>, ["~> 5.0"])
31
31
 
32
32
  s.add_development_dependency(%q<isolate>, "~> 3.1")
33
33
  s.add_development_dependency(%q<olddoc>, "~> 1.0")
@@ -25,7 +25,11 @@ t_begin "stops a regular request" && {
25
25
  rm -f $tmp
26
26
  dbgcat curl_err
27
27
  dbgcat curl_out
28
- grep 413 $curl_err
28
+ if ! grep 413 $curl_err
29
+ then
30
+ # send error as documented in curl(1) manpage
31
+ grep -F '(55)' $curl_err
32
+ fi
29
33
  test -e $ok
30
34
  }
31
35
 
@@ -36,7 +40,11 @@ t_begin "stops a large chunked request" && {
36
40
  http://$listen/ > $curl_out 2> $curl_err || > $ok
37
41
  dbgcat curl_err
38
42
  dbgcat curl_out
39
- grep 413 $curl_err
43
+ if ! grep 413 $curl_err
44
+ then
45
+ # send error as documented in curl(1) manpage
46
+ grep -F '(55)' $curl_err
47
+ fi
40
48
  test -e $ok
41
49
  }
42
50
 
@@ -20,7 +20,7 @@
20
20
  gem 'rack', '1.6.4'
21
21
  gem 'kcar', '0.5.0'
22
22
  gem 'raindrops', '0.13.0'
23
- gem 'unicorn', '4.9.0'
23
+ gem 'unicorn', '5.0.1'
24
24
 
25
25
  if engine == "ruby"
26
26
  gem 'sendfile', '1.2.2'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rainbows
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.7.0
4
+ version: 5.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rainbows! hackers
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-10-19 00:00:00.000000000 Z
11
+ date: 2015-11-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -44,14 +44,14 @@ dependencies:
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '4.8'
47
+ version: '5.0'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '4.8'
54
+ version: '5.0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: isolate
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -139,6 +139,7 @@ extra_rdoc_files:
139
139
  - HACKING
140
140
  files:
141
141
  - ".document"
142
+ - ".gitattributes"
142
143
  - ".gitignore"
143
144
  - ".manifest"
144
145
  - ".olddoc.yml"