rainbows 0.94.0 → 0.95.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.document +1 -0
- data/.manifest +18 -0
- data/ChangeLog +394 -226
- data/GIT-VERSION-FILE +1 -1
- data/GIT-VERSION-GEN +1 -1
- data/GNUmakefile +6 -4
- data/NEWS +18 -0
- data/README +13 -5
- data/Static_Files +71 -0
- data/TODO +12 -0
- data/Test_Suite +1 -1
- data/bin/rainbows +1 -4
- data/lib/rainbows/actor_spawn.rb +1 -1
- data/lib/rainbows/app_pool.rb +1 -1
- data/lib/rainbows/base.rb +79 -89
- data/lib/rainbows/byte_slice.rb +17 -0
- data/lib/rainbows/configurator.rb +46 -0
- data/lib/rainbows/const.rb +2 -2
- data/lib/rainbows/dev_fd_response.rb +52 -44
- data/lib/rainbows/error.rb +1 -0
- data/lib/rainbows/ev_core.rb +3 -2
- data/lib/rainbows/event_machine.rb +26 -24
- data/lib/rainbows/fiber/base.rb +30 -40
- data/lib/rainbows/fiber/body.rb +34 -0
- data/lib/rainbows/fiber/io.rb +28 -8
- data/lib/rainbows/fiber/queue.rb +1 -0
- data/lib/rainbows/fiber/rev.rb +4 -2
- data/lib/rainbows/fiber.rb +1 -0
- data/lib/rainbows/fiber_pool.rb +2 -2
- data/lib/rainbows/fiber_spawn.rb +2 -2
- data/lib/rainbows/http_response.rb +20 -31
- data/lib/rainbows/http_server.rb +3 -4
- data/lib/rainbows/max_body.rb +1 -0
- data/lib/rainbows/never_block/event_machine.rb +2 -0
- data/lib/rainbows/never_block.rb +5 -4
- data/lib/rainbows/queue_pool.rb +1 -0
- data/lib/rainbows/response/body.rb +119 -0
- data/lib/rainbows/response.rb +43 -0
- data/lib/rainbows/rev/client.rb +79 -9
- data/lib/rainbows/rev/core.rb +4 -0
- data/lib/rainbows/rev/deferred_response.rb +1 -44
- data/lib/rainbows/rev/heartbeat.rb +1 -0
- data/lib/rainbows/rev/master.rb +1 -0
- data/lib/rainbows/rev/sendfile.rb +26 -0
- data/lib/rainbows/rev/thread.rb +2 -1
- data/lib/rainbows/rev.rb +2 -0
- data/lib/rainbows/rev_fiber_spawn.rb +3 -1
- data/lib/rainbows/rev_thread_pool.rb +7 -5
- data/lib/rainbows/rev_thread_spawn.rb +2 -2
- data/lib/rainbows/revactor.rb +146 -146
- data/lib/rainbows/sendfile.rb +10 -21
- data/lib/rainbows/server_token.rb +39 -0
- data/lib/rainbows/stream_file.rb +14 -0
- data/lib/rainbows/tee_input.rb +1 -0
- data/lib/rainbows/thread_pool.rb +12 -7
- data/lib/rainbows/thread_spawn.rb +2 -3
- data/lib/rainbows/writer_thread_pool.rb +13 -7
- data/lib/rainbows/writer_thread_spawn.rb +12 -9
- data/lib/rainbows.rb +16 -45
- data/rainbows.gemspec +8 -8
- data/t/.gitignore +1 -1
- data/t/GNUmakefile +26 -16
- data/t/README +1 -1
- data/t/async-response-no-autochunk.ru +0 -1
- data/t/async-response.ru +0 -1
- data/t/cramp/rainsocket.ru +26 -0
- data/t/fork-sleep.ru +0 -1
- data/t/my-tap-lib.sh +3 -2
- data/t/simple-http_ActorSpawn.ru +9 -0
- data/t/t0009-broken-app.sh +1 -1
- data/t/t0009.ru +0 -1
- data/t/t0011-close-on-exec-set.sh +1 -1
- data/t/t0015-working_directory.sh +56 -0
- data/t/t0016-onenine-encoding-is-tricky.sh +28 -0
- data/t/t0016.rb +15 -0
- data/t/t0020-large-sendfile-response.sh +141 -0
- data/t/t0300-async_sinatra.sh +0 -6
- data/t/t0501-cramp-rainsocket.sh +38 -0
- data/t/t9001-sendfile-to-path.sh +5 -4
- data/t/t9002-server-token.sh +37 -0
- data/t/t9002.ru +4 -0
- data/t/test-lib.sh +1 -1
- data/t/test_isolate.rb +14 -11
- metadata +87 -18
@@ -48,8 +48,9 @@ module Rainbows
|
|
48
48
|
|
49
49
|
include Base
|
50
50
|
|
51
|
-
class Client < EM::Connection
|
51
|
+
class Client < EM::Connection # :nodoc: all
|
52
52
|
include Rainbows::EvCore
|
53
|
+
include Rainbows::Response
|
53
54
|
G = Rainbows::G
|
54
55
|
|
55
56
|
def initialize(io)
|
@@ -70,7 +71,7 @@ module Rainbows
|
|
70
71
|
begin
|
71
72
|
@env[RACK_INPUT] = @input
|
72
73
|
@env[REMOTE_ADDR] = @remote_addr
|
73
|
-
@env[ASYNC_CALLBACK] = method(:
|
74
|
+
@env[ASYNC_CALLBACK] = method(:em_write_response)
|
74
75
|
|
75
76
|
# we're not sure if anybody uses this, but Thin sets it, too
|
76
77
|
@env[ASYNC_CLOSE] = EM::DefaultDeferrable.new
|
@@ -80,11 +81,11 @@ module Rainbows
|
|
80
81
|
# too tricky to support pipelining with :async since the
|
81
82
|
# second (pipelined) request could be a stuck behind a
|
82
83
|
# long-running async response
|
83
|
-
(response.nil? || -1 == response
|
84
|
+
(response.nil? || -1 == response[0]) and return @state = :close
|
84
85
|
|
85
86
|
alive = @hp.keepalive? && G.alive
|
86
87
|
out = [ alive ? CONN_ALIVE : CONN_CLOSE ] if @hp.headers?
|
87
|
-
|
88
|
+
em_write_response(response, out, alive)
|
88
89
|
|
89
90
|
if alive
|
90
91
|
@env.clear
|
@@ -98,32 +99,29 @@ module Rainbows
|
|
98
99
|
end while true
|
99
100
|
end
|
100
101
|
|
101
|
-
def
|
102
|
-
@body = body = response
|
102
|
+
def em_write_response(response, out = [ CONN_CLOSE ], alive = false)
|
103
|
+
@body = body = response[2]
|
103
104
|
if body.respond_to?(:errback) && body.respond_to?(:callback)
|
104
105
|
body.callback { quit }
|
105
106
|
body.errback { quit }
|
106
|
-
|
107
|
+
write_header(self, response, out)
|
108
|
+
write_body_each(self, body)
|
107
109
|
return
|
108
110
|
elsif ! body.respond_to?(:to_path)
|
109
|
-
|
111
|
+
write_response(self, response, out)
|
110
112
|
quit unless alive
|
111
113
|
return
|
112
114
|
end
|
113
115
|
|
114
116
|
headers = Rack::Utils::HeaderHash.new(response[1])
|
115
|
-
|
116
|
-
io = body.to_io if body.respond_to?(:to_io)
|
117
|
-
io ||= IO.new($1.to_i) if path =~ %r{\A/dev/fd/(\d+)\z}
|
118
|
-
io ||= File.open(path, 'rb') # could be a named pipe
|
119
|
-
|
117
|
+
io = body_to_io(body)
|
120
118
|
st = io.stat
|
119
|
+
|
121
120
|
if st.file?
|
122
121
|
headers.delete('Transfer-Encoding')
|
123
122
|
headers['Content-Length'] ||= st.size.to_s
|
124
|
-
|
125
|
-
|
126
|
-
stream = stream_file_data(path)
|
123
|
+
write_header(self, [ response[0], headers ], out)
|
124
|
+
stream = stream_file_data(body.to_path)
|
127
125
|
stream.callback { quit } unless alive
|
128
126
|
elsif st.socket? || st.pipe?
|
129
127
|
do_chunk = !!(headers['Transfer-Encoding'] =~ %r{\Achunked\z}i)
|
@@ -133,15 +131,14 @@ module Rainbows
|
|
133
131
|
else
|
134
132
|
out[0] = CONN_CLOSE
|
135
133
|
end
|
136
|
-
|
137
|
-
HttpResponse.write(self, response, out)
|
134
|
+
write_header(self, [ response[0], headers ], out)
|
138
135
|
if do_chunk
|
139
136
|
EM.watch(io, ResponseChunkPipe, self).notify_readable = true
|
140
137
|
else
|
141
138
|
EM.enable_proxy(EM.attach(io, ResponsePipe, self), self, 16384)
|
142
139
|
end
|
143
140
|
else
|
144
|
-
|
141
|
+
write_response(self, response, out)
|
145
142
|
end
|
146
143
|
end
|
147
144
|
|
@@ -152,7 +149,7 @@ module Rainbows
|
|
152
149
|
end
|
153
150
|
end
|
154
151
|
|
155
|
-
module ResponsePipe
|
152
|
+
module ResponsePipe # :nodoc: all
|
156
153
|
def initialize(client)
|
157
154
|
@client = client
|
158
155
|
end
|
@@ -163,7 +160,7 @@ module Rainbows
|
|
163
160
|
end
|
164
161
|
end
|
165
162
|
|
166
|
-
module ResponseChunkPipe
|
163
|
+
module ResponseChunkPipe # :nodoc: all
|
167
164
|
include ResponsePipe
|
168
165
|
|
169
166
|
def unbind
|
@@ -190,7 +187,7 @@ module Rainbows
|
|
190
187
|
end
|
191
188
|
end
|
192
189
|
|
193
|
-
module Server
|
190
|
+
module Server # :nodoc: all
|
194
191
|
|
195
192
|
def close
|
196
193
|
detach
|
@@ -208,7 +205,7 @@ module Rainbows
|
|
208
205
|
# Middleware that will run the app dispatch in a separate thread.
|
209
206
|
# This middleware is automatically loaded by Rainbows! when using
|
210
207
|
# EventMachine and if the app responds to the +deferred?+ method.
|
211
|
-
class TryDefer < Struct.new(:app)
|
208
|
+
class TryDefer < Struct.new(:app) # :nodoc: all
|
212
209
|
|
213
210
|
def initialize(app)
|
214
211
|
# the entire app becomes multithreaded, even the root (non-deferred)
|
@@ -229,10 +226,15 @@ module Rainbows
|
|
229
226
|
end
|
230
227
|
end
|
231
228
|
|
229
|
+
def init_worker_process(worker) # :nodoc:
|
230
|
+
Rainbows::Response.setup(Rainbows::EventMachine::Client)
|
231
|
+
super
|
232
|
+
end
|
233
|
+
|
232
234
|
# runs inside each forked worker, this sits around and waits
|
233
235
|
# for connections and doesn't die until the parent dies (or is
|
234
236
|
# given a INT, QUIT, or TERM signal)
|
235
|
-
def worker_loop(worker)
|
237
|
+
def worker_loop(worker) # :nodoc:
|
236
238
|
init_worker_process(worker)
|
237
239
|
G.server.app.respond_to?(:deferred?) and
|
238
240
|
G.server.app = TryDefer[G.server.app]
|
data/lib/rainbows/fiber/base.rb
CHANGED
@@ -1,14 +1,15 @@
|
|
1
1
|
# -*- encoding: binary -*-
|
2
|
+
# :enddoc:
|
2
3
|
require 'rainbows/fiber/io'
|
3
4
|
|
4
5
|
module Rainbows
|
5
6
|
module Fiber
|
6
7
|
|
7
|
-
# blocked readers (key: Rainbows::Fiber::IO object
|
8
|
-
RD =
|
8
|
+
# blocked readers (key: fileno, value: Rainbows::Fiber::IO object)
|
9
|
+
RD = []
|
9
10
|
|
10
|
-
# blocked writers (key: Rainbows::Fiber::IO object
|
11
|
-
WR =
|
11
|
+
# blocked writers (key: fileno, value: Rainbows::Fiber::IO object)
|
12
|
+
WR = []
|
12
13
|
|
13
14
|
# sleeping fibers go here (key: Fiber object, value: wakeup time)
|
14
15
|
ZZ = {}.compare_by_identity
|
@@ -35,9 +36,10 @@ module Rainbows
|
|
35
36
|
def schedule(&block)
|
36
37
|
ret = begin
|
37
38
|
G.tick
|
38
|
-
RD.
|
39
|
+
RD.compact.each { |c| c.f.resume } # attempt to time out idle clients
|
39
40
|
t = schedule_sleepers
|
40
|
-
Kernel.select(RD.
|
41
|
+
Kernel.select(RD.compact.concat(LISTENERS),
|
42
|
+
WR.compact, nil, t) or return
|
41
43
|
rescue Errno::EINTR
|
42
44
|
retry
|
43
45
|
rescue Errno::EBADF, TypeError
|
@@ -46,10 +48,10 @@ module Rainbows
|
|
46
48
|
end or return
|
47
49
|
|
48
50
|
# active writers first, then _all_ readers for keepalive timeout
|
49
|
-
ret[1].concat(RD.
|
51
|
+
ret[1].concat(RD.compact).each { |c| c.f.resume }
|
50
52
|
|
51
53
|
# accept is an expensive syscall, filter out listeners we don't want
|
52
|
-
(ret
|
54
|
+
(ret[0] & LISTENERS).each(&block)
|
53
55
|
end
|
54
56
|
|
55
57
|
# wakes up any sleepers that need to be woken and
|
@@ -61,54 +63,42 @@ module Rainbows
|
|
61
63
|
ZZ.delete_if { |fib, time|
|
62
64
|
if now >= time
|
63
65
|
fibs << fib
|
64
|
-
now = Time.now
|
65
66
|
else
|
66
67
|
max = time
|
67
68
|
false
|
68
69
|
end
|
69
70
|
}
|
70
71
|
fibs.each { |fib| fib.resume }
|
72
|
+
now = Time.now
|
71
73
|
max.nil? || max > (now + 1) ? 1 : max - now
|
72
74
|
end
|
73
75
|
|
74
|
-
def
|
75
|
-
G.cur += 1
|
76
|
+
def wait_headers_readable(client)
|
76
77
|
io = client.to_io
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
env[CLIENT_IO] = client
|
89
|
-
env[RACK_INPUT] = 0 == hp.content_length ?
|
90
|
-
HttpRequest::NULL_IO : TeeInput.new(client, env, hp, buf)
|
91
|
-
env[REMOTE_ADDR] = remote_addr
|
92
|
-
response = APP.call(env.update(RACK_DEFAULTS))
|
93
|
-
|
94
|
-
if 100 == response.first.to_i
|
95
|
-
client.write(EXPECT_100_RESPONSE)
|
96
|
-
env.delete(HTTP_EXPECT)
|
97
|
-
response = APP.call(env)
|
98
|
-
end
|
78
|
+
expire = nil
|
79
|
+
begin
|
80
|
+
return io.recv_nonblock(1, Socket::MSG_PEEK)
|
81
|
+
rescue Errno::EAGAIN
|
82
|
+
return if expire && expire < Time.now
|
83
|
+
expire ||= Time.now + G.kato
|
84
|
+
client.wait_readable
|
85
|
+
retry
|
86
|
+
end
|
87
|
+
end
|
99
88
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
end while alive and hp.reset.nil? and env.clear
|
104
|
-
rescue => e
|
105
|
-
Error.write(io, e)
|
89
|
+
def process_client(client)
|
90
|
+
G.cur += 1
|
91
|
+
super(client) # see Rainbows::Base
|
106
92
|
ensure
|
107
93
|
G.cur -= 1
|
108
94
|
ZZ.delete(client.f)
|
109
|
-
client.close
|
110
95
|
end
|
111
96
|
|
97
|
+
def self.setup(klass, app)
|
98
|
+
require 'rainbows/fiber/body'
|
99
|
+
klass.__send__(:include, Rainbows::Fiber::Body)
|
100
|
+
self.const_set(:APP, app)
|
101
|
+
end
|
112
102
|
end
|
113
103
|
end
|
114
104
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# -*- encoding: binary -*-
|
2
|
+
# :enddoc:
|
3
|
+
# non-portable body handling for Fiber-based concurrency goes here
|
4
|
+
# this module is required and included in worker processes only
|
5
|
+
# this is meant to be included _after_ Rainbows::Response::Body
|
6
|
+
module Rainbows::Fiber::Body # :nodoc:
|
7
|
+
|
8
|
+
# TODO non-blocking splice(2) under Linux
|
9
|
+
ALIASES = {
|
10
|
+
:write_body_stream => :write_body_each
|
11
|
+
}
|
12
|
+
|
13
|
+
# the sendfile 1.0.0+ gem includes IO#sendfile_nonblock
|
14
|
+
if ::IO.method_defined?(:sendfile_nonblock)
|
15
|
+
def write_body_file(client, body)
|
16
|
+
sock, off = client.to_io, 0
|
17
|
+
begin
|
18
|
+
off += sock.sendfile_nonblock(body, off, 0x10000)
|
19
|
+
rescue Errno::EAGAIN
|
20
|
+
client.wait_writable
|
21
|
+
rescue EOFError
|
22
|
+
break
|
23
|
+
end while true
|
24
|
+
end
|
25
|
+
else
|
26
|
+
ALIASES[:write_body] = :write_body_each
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.included(klass)
|
30
|
+
ALIASES.each do |new_method, orig_method|
|
31
|
+
klass.__send__(:alias_method, new_method, orig_method)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/rainbows/fiber/io.rb
CHANGED
@@ -7,6 +7,20 @@ module Rainbows
|
|
7
7
|
# interface that yields away from the current Fiber whenever
|
8
8
|
# the underlying IO object cannot read or write
|
9
9
|
class IO < Struct.new(:to_io, :f)
|
10
|
+
include Rainbows::ByteSlice
|
11
|
+
|
12
|
+
# :stopdoc:
|
13
|
+
LOCALHOST = Unicorn::HttpRequest::LOCALHOST
|
14
|
+
|
15
|
+
# needed to write errors with
|
16
|
+
def write_nonblock(buf)
|
17
|
+
to_io.write_nonblock(buf)
|
18
|
+
end
|
19
|
+
|
20
|
+
# enough for Rainbows.addr
|
21
|
+
def peeraddr
|
22
|
+
to_io.respond_to?(:peeraddr) ? to_io.peeraddr : [ LOCALHOST ]
|
23
|
+
end
|
10
24
|
|
11
25
|
# for wrapping output response bodies
|
12
26
|
def each(&block)
|
@@ -19,27 +33,33 @@ module Rainbows
|
|
19
33
|
end
|
20
34
|
|
21
35
|
def close
|
22
|
-
|
23
|
-
WR
|
36
|
+
fileno = to_io.fileno
|
37
|
+
RD[fileno] = WR[fileno] = nil
|
24
38
|
to_io.close unless to_io.closed?
|
25
39
|
end
|
26
40
|
|
41
|
+
def closed?
|
42
|
+
to_io.closed?
|
43
|
+
end
|
44
|
+
|
27
45
|
def wait_readable
|
28
|
-
|
46
|
+
fileno = to_io.fileno
|
47
|
+
RD[fileno] = self
|
29
48
|
::Fiber.yield
|
30
|
-
RD
|
49
|
+
RD[fileno] = nil
|
31
50
|
end
|
32
51
|
|
33
52
|
def wait_writable
|
34
|
-
|
53
|
+
fileno = to_io.fileno
|
54
|
+
WR[fileno] = self
|
35
55
|
::Fiber.yield
|
36
|
-
WR
|
56
|
+
WR[fileno] = nil
|
37
57
|
end
|
38
58
|
|
39
59
|
def write(buf)
|
40
60
|
begin
|
41
|
-
(w = to_io.write_nonblock(buf)) == buf.
|
42
|
-
buf = buf
|
61
|
+
(w = to_io.write_nonblock(buf)) == buf.bytesize and return
|
62
|
+
buf = byte_slice(buf, w..-1)
|
43
63
|
rescue Errno::EAGAIN
|
44
64
|
wait_writable
|
45
65
|
retry
|
data/lib/rainbows/fiber/queue.rb
CHANGED
data/lib/rainbows/fiber/rev.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# -*- encoding: binary -*-
|
2
|
+
# :enddoc:
|
2
3
|
require 'rev'
|
3
4
|
require 'rainbows/fiber'
|
4
5
|
require 'rainbows/fiber/io'
|
@@ -52,6 +53,7 @@ module Rainbows::Fiber
|
|
52
53
|
include Unicorn
|
53
54
|
include Rainbows
|
54
55
|
include Rainbows::Const
|
56
|
+
include Rainbows::Response
|
55
57
|
FIO = Rainbows::Fiber::IO
|
56
58
|
|
57
59
|
def to_io
|
@@ -91,7 +93,7 @@ module Rainbows::Fiber
|
|
91
93
|
env[REMOTE_ADDR] = remote_addr
|
92
94
|
response = APP.call(env.update(RACK_DEFAULTS))
|
93
95
|
|
94
|
-
if 100 == response.
|
96
|
+
if 100 == response[0].to_i
|
95
97
|
client.write(EXPECT_100_RESPONSE)
|
96
98
|
env.delete(HTTP_EXPECT)
|
97
99
|
response = APP.call(env)
|
@@ -99,7 +101,7 @@ module Rainbows::Fiber
|
|
99
101
|
|
100
102
|
alive = hp.keepalive? && G.alive
|
101
103
|
out = [ alive ? CONN_ALIVE : CONN_CLOSE ] if hp.headers?
|
102
|
-
|
104
|
+
write_response(client, response, out)
|
103
105
|
end while alive and hp.reset.nil? and env.clear
|
104
106
|
rescue => e
|
105
107
|
Error.write(io, e)
|
data/lib/rainbows/fiber.rb
CHANGED
data/lib/rainbows/fiber_pool.rb
CHANGED
@@ -16,7 +16,7 @@ module Rainbows
|
|
16
16
|
module FiberPool
|
17
17
|
include Fiber::Base
|
18
18
|
|
19
|
-
def worker_loop(worker)
|
19
|
+
def worker_loop(worker) # :nodoc:
|
20
20
|
init_worker_process(worker)
|
21
21
|
pool = []
|
22
22
|
worker_connections.times {
|
@@ -24,7 +24,7 @@ module Rainbows
|
|
24
24
|
process_client(::Fiber.yield) while pool << ::Fiber.current
|
25
25
|
}.resume # resume to hit ::Fiber.yield so it waits on a client
|
26
26
|
}
|
27
|
-
Fiber::Base.
|
27
|
+
Fiber::Base.setup(self.class, app)
|
28
28
|
|
29
29
|
begin
|
30
30
|
schedule do |l|
|
data/lib/rainbows/fiber_spawn.rb
CHANGED
@@ -13,9 +13,9 @@ module Rainbows
|
|
13
13
|
module FiberSpawn
|
14
14
|
include Fiber::Base
|
15
15
|
|
16
|
-
def worker_loop(worker)
|
16
|
+
def worker_loop(worker) # :nodoc:
|
17
17
|
init_worker_process(worker)
|
18
|
-
Fiber::Base.
|
18
|
+
Fiber::Base.setup(self.class, app)
|
19
19
|
limit = worker_connections
|
20
20
|
fio = Rainbows::Fiber::IO
|
21
21
|
|
@@ -1,38 +1,27 @@
|
|
1
1
|
# -*- encoding: binary -*-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
class
|
7
|
-
|
8
|
-
|
9
|
-
|
2
|
+
# :enddoc:
|
3
|
+
# deprecated, use Rainbows::Response instead
|
4
|
+
# Cramp 0.11 relies on this, and is only activated by Cramp
|
5
|
+
if defined?(Cramp) && defined?(Rainbows::EventMachine::Client)
|
6
|
+
class Rainbows::HttpResponse
|
7
|
+
class << self
|
8
|
+
include Rainbows::Response
|
9
|
+
alias write write_response
|
10
|
+
end
|
11
|
+
end
|
10
12
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
else
|
18
|
-
out << "#{key}: #{value}\r\n"
|
19
|
-
end
|
13
|
+
module Rainbows::EventMachine::CrampSocket
|
14
|
+
def write_header(_, response, out)
|
15
|
+
if websocket?
|
16
|
+
write web_socket_upgrade_data
|
17
|
+
web_socket_handshake!
|
18
|
+
out = nil # disable response headers
|
20
19
|
end
|
21
|
-
|
22
|
-
"HTTP/1.1 #{status}\r\n" \
|
23
|
-
"Date: #{Time.now.httpdate}\r\n" \
|
24
|
-
"Status: #{status}\r\n" \
|
25
|
-
"#{out.join('')}\r\n"
|
20
|
+
super(self, response, out)
|
26
21
|
end
|
22
|
+
end
|
27
23
|
|
28
|
-
|
29
|
-
|
30
|
-
out.instance_of?(Array) and
|
31
|
-
socket.write(header_string(status, headers, out))
|
32
|
-
|
33
|
-
body.each { |chunk| socket.write(chunk) }
|
34
|
-
ensure
|
35
|
-
body.respond_to?(:close) and body.close
|
36
|
-
end
|
24
|
+
class Rainbows::EventMachine::Client
|
25
|
+
include Rainbows::EventMachine::CrampSocket
|
37
26
|
end
|
38
27
|
end
|
data/lib/rainbows/http_server.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# -*- encoding: binary -*-
|
2
|
+
# :enddoc:
|
2
3
|
module Rainbows
|
3
4
|
|
4
5
|
class HttpServer < ::Unicorn::HttpServer
|
@@ -33,10 +34,8 @@ module Rainbows
|
|
33
34
|
# connection we accept without wasting cycles. That added to the
|
34
35
|
# fact that we let clients keep idle connections open for long
|
35
36
|
# periods of time means we have to chmod at a fixed interval.
|
36
|
-
alias_method :set_timeout, :timeout=
|
37
|
-
undef_method :timeout=
|
38
37
|
def timeout=(nr)
|
39
|
-
|
38
|
+
super(nr + 1)
|
40
39
|
end
|
41
40
|
#:startdoc:
|
42
41
|
|
@@ -70,7 +69,7 @@ module Rainbows
|
|
70
69
|
|
71
70
|
def worker_connections(*args)
|
72
71
|
return @worker_connections if args.empty?
|
73
|
-
nr = args
|
72
|
+
nr = args[0]
|
74
73
|
(Integer === nr && nr > 0) or
|
75
74
|
raise ArgumentError, "worker_connections must be a positive Integer"
|
76
75
|
@worker_connections = nr
|
data/lib/rainbows/max_body.rb
CHANGED
data/lib/rainbows/never_block.rb
CHANGED
@@ -18,13 +18,14 @@ module Rainbows
|
|
18
18
|
#
|
19
19
|
module NeverBlock
|
20
20
|
|
21
|
+
# :stopdoc:
|
21
22
|
DEFAULTS = {
|
22
23
|
:pool_size => 20, # same default size used by NB
|
23
24
|
:backend => :EventMachine, # NeverBlock doesn't support Rev yet
|
24
25
|
}
|
25
26
|
|
26
27
|
# same pool size NB core itself uses
|
27
|
-
def self.setup
|
28
|
+
def self.setup # :nodoc:
|
28
29
|
DEFAULTS.each { |k,v| O[k] ||= v }
|
29
30
|
Integer === O[:pool_size] && O[:pool_size] > 0 or
|
30
31
|
raise ArgumentError, "pool_size must a be an Integer > 0"
|
@@ -34,7 +35,7 @@ module Rainbows
|
|
34
35
|
G.server.extend(Core)
|
35
36
|
end
|
36
37
|
|
37
|
-
module Core
|
38
|
+
module Core # :nodoc: all
|
38
39
|
def self.setup
|
39
40
|
self.const_set(:POOL, ::NB::Pool::FiberPool.new(O[:pool_size]))
|
40
41
|
base = O[:backend].to_s.gsub!(/([a-z])([A-Z])/, '\1_\2').downcase!
|
@@ -57,9 +58,7 @@ module Rainbows
|
|
57
58
|
end
|
58
59
|
end
|
59
60
|
end
|
60
|
-
end
|
61
61
|
|
62
|
-
module Core
|
63
62
|
def init_worker_process(worker)
|
64
63
|
super
|
65
64
|
Core.setup
|
@@ -67,5 +66,7 @@ module Rainbows
|
|
67
66
|
end
|
68
67
|
end
|
69
68
|
|
69
|
+
# :startdoc:
|
70
|
+
|
70
71
|
end
|
71
72
|
end
|