rainbows 2.0.0 → 2.0.1
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/.manifest +2 -0
- data/ChangeLog +38 -1
- data/GIT-VERSION-FILE +1 -1
- data/GIT-VERSION-GEN +1 -1
- data/NEWS +6 -0
- data/lib/rainbows/const.rb +1 -1
- data/lib/rainbows/ev_core.rb +46 -49
- data/lib/rainbows/ev_core/cap_input.rb +21 -0
- data/lib/rainbows/rev/client.rb +7 -3
- data/t/t0106-rack-input-keepalive.sh +72 -0
- data/t/test_isolate.rb +1 -1
- metadata +7 -4
data/.manifest
CHANGED
|
@@ -34,6 +34,7 @@ lib/rainbows/const.rb
|
|
|
34
34
|
lib/rainbows/dev_fd_response.rb
|
|
35
35
|
lib/rainbows/error.rb
|
|
36
36
|
lib/rainbows/ev_core.rb
|
|
37
|
+
lib/rainbows/ev_core/cap_input.rb
|
|
37
38
|
lib/rainbows/event_machine.rb
|
|
38
39
|
lib/rainbows/event_machine/response_chunk_pipe.rb
|
|
39
40
|
lib/rainbows/event_machine/response_pipe.rb
|
|
@@ -183,6 +184,7 @@ t/t0102-rack-input-short.sh
|
|
|
183
184
|
t/t0103-rack-input-limit.sh
|
|
184
185
|
t/t0104-rack-input-limit-tiny.sh
|
|
185
186
|
t/t0105-rack-input-limit-bigger.sh
|
|
187
|
+
t/t0106-rack-input-keepalive.sh
|
|
186
188
|
t/t0200-async-response.sh
|
|
187
189
|
t/t0201-async-response-no-autochunk.sh
|
|
188
190
|
t/t0300-async_sinatra.sh
|
data/ChangeLog
CHANGED
|
@@ -1,5 +1,42 @@
|
|
|
1
|
-
ChangeLog from git://git.bogomips.org/rainbows.git (v0.97.0..v2.0.
|
|
1
|
+
ChangeLog from git://git.bogomips.org/rainbows.git (v0.97.0..v2.0.1)
|
|
2
2
|
|
|
3
|
+
commit b4835c6d542c6369f2523ab68fc41b0202d7c6dc
|
|
4
|
+
Author: Eric Wong <normalperson@yhbt.net>
|
|
5
|
+
Date: Fri Dec 3 01:23:11 2010 +0000
|
|
6
|
+
|
|
7
|
+
Rainbows! 2.0.1 - upload pipelining fixes
|
|
8
|
+
|
|
9
|
+
For HTTP clients living on the edge and pipelining uploads, we
|
|
10
|
+
now fully support pipelined requests (as long as the application
|
|
11
|
+
consumes each request in its entirety).
|
|
12
|
+
|
|
13
|
+
commit c096e735efea5050b0559748633403f0387ea3b3
|
|
14
|
+
Author: Eric Wong <normalperson@yhbt.net>
|
|
15
|
+
Date: Fri Dec 3 01:12:08 2010 +0000
|
|
16
|
+
|
|
17
|
+
fix pipelining of requests with bodies
|
|
18
|
+
|
|
19
|
+
All synchronous models have this fixed in unicorn 3.0.1,
|
|
20
|
+
so only Rev and EventMachine-based concurrency models
|
|
21
|
+
require code changes.
|
|
22
|
+
|
|
23
|
+
commit 64889d9136fa5466269232c26a2f235dd763d8f0
|
|
24
|
+
Author: Eric Wong <normalperson@yhbt.net>
|
|
25
|
+
Date: Thu Dec 2 07:38:14 2010 +0000
|
|
26
|
+
|
|
27
|
+
ev_core: refactor and split cap_input out
|
|
28
|
+
|
|
29
|
+
Hopefully it makes more sense now and is easier to
|
|
30
|
+
digest for new hackers.
|
|
31
|
+
|
|
32
|
+
commit 945b5760d86b9dd00e65bd0625b98cf75f6a8257
|
|
33
|
+
Author: Eric Wong <normalperson@yhbt.net>
|
|
34
|
+
Date: Wed Dec 1 21:29:34 2010 -0800
|
|
35
|
+
|
|
36
|
+
ev_core: split out prepare_request_body
|
|
37
|
+
|
|
38
|
+
We may have other uses for this in the future...
|
|
39
|
+
|
|
3
40
|
commit 90789761f0cc78d3726f3a2eda1c5fe95c015ac2
|
|
4
41
|
Author: Eric Wong <normalperson@yhbt.net>
|
|
5
42
|
Date: Fri Nov 19 19:09:59 2010 -0800
|
data/GIT-VERSION-FILE
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
GIT_VERSION = 2.0.
|
|
1
|
+
GIT_VERSION = 2.0.1
|
data/GIT-VERSION-GEN
CHANGED
data/NEWS
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
=== 2.0.1 / 2010-12-03 01:26 UTC
|
|
2
|
+
|
|
3
|
+
For HTTP clients living on the edge and pipelining uploads, we
|
|
4
|
+
now fully support pipelined requests (as long as the application
|
|
5
|
+
consumes each request in its entirety).
|
|
6
|
+
|
|
1
7
|
=== 2.0.0 / 2010-11-20 03:10 UTC
|
|
2
8
|
|
|
3
9
|
This release is targeted at the minority of web applications
|
data/lib/rainbows/const.rb
CHANGED
data/lib/rainbows/ev_core.rb
CHANGED
|
@@ -7,6 +7,7 @@ module Rainbows::EvCore
|
|
|
7
7
|
G = Rainbows::G
|
|
8
8
|
NULL_IO = Unicorn::HttpRequest::NULL_IO
|
|
9
9
|
HttpParser = Unicorn::HttpParser
|
|
10
|
+
autoload :CapInput, 'rainbows/ev_core/cap_input'
|
|
10
11
|
|
|
11
12
|
# Apps may return this Rack response: AsyncResponse = [ -1, {}, [] ]
|
|
12
13
|
ASYNC_CALLBACK = "async.callback".freeze
|
|
@@ -25,6 +26,9 @@ module Rainbows::EvCore
|
|
|
25
26
|
@state = :close
|
|
26
27
|
end
|
|
27
28
|
|
|
29
|
+
def want_more
|
|
30
|
+
end
|
|
31
|
+
|
|
28
32
|
def handle_error(e)
|
|
29
33
|
msg = Rainbows::Error.response(e) and write(msg)
|
|
30
34
|
ensure
|
|
@@ -43,33 +47,41 @@ module Rainbows::EvCore
|
|
|
43
47
|
rv
|
|
44
48
|
end
|
|
45
49
|
|
|
50
|
+
def prepare_request_body
|
|
51
|
+
# since we don't do streaming input, we have no choice but
|
|
52
|
+
# to take over 100-continue handling from the Rack application
|
|
53
|
+
if @env[HTTP_EXPECT] =~ /\A100-continue\z/i
|
|
54
|
+
write(EXPECT_100_RESPONSE)
|
|
55
|
+
@env.delete(HTTP_EXPECT)
|
|
56
|
+
end
|
|
57
|
+
@input = mkinput
|
|
58
|
+
@hp.filter_body(@buf2 = "", @buf)
|
|
59
|
+
@input << @buf2
|
|
60
|
+
on_read("")
|
|
61
|
+
end
|
|
62
|
+
|
|
46
63
|
# TeeInput doesn't map too well to this right now...
|
|
47
64
|
def on_read(data)
|
|
48
65
|
case @state
|
|
49
66
|
when :headers
|
|
50
67
|
@buf << data
|
|
51
|
-
@hp.parse or return
|
|
68
|
+
@hp.parse or return want_more
|
|
52
69
|
@state = :body
|
|
53
|
-
|
|
54
|
-
if len == 0
|
|
70
|
+
if 0 == @hp.content_length
|
|
55
71
|
@input = NULL_IO
|
|
56
72
|
app_call # common case
|
|
57
73
|
else # nil or len > 0
|
|
58
|
-
|
|
59
|
-
# to take over 100-continue handling from the Rack application
|
|
60
|
-
if @env[HTTP_EXPECT] =~ /\A100-continue\z/i
|
|
61
|
-
write(EXPECT_100_RESPONSE)
|
|
62
|
-
@env.delete(HTTP_EXPECT)
|
|
63
|
-
end
|
|
64
|
-
@input = CapInput.new(len, self)
|
|
65
|
-
@hp.filter_body(@buf2 = "", @buf)
|
|
66
|
-
@input << @buf2
|
|
67
|
-
on_read("")
|
|
74
|
+
prepare_request_body
|
|
68
75
|
end
|
|
69
76
|
when :body
|
|
70
77
|
if @hp.body_eof?
|
|
71
|
-
@
|
|
72
|
-
|
|
78
|
+
if @hp.content_length
|
|
79
|
+
@input.rewind
|
|
80
|
+
app_call
|
|
81
|
+
else
|
|
82
|
+
@state = :trailers
|
|
83
|
+
on_read(data)
|
|
84
|
+
end
|
|
73
85
|
elsif data.size > 0
|
|
74
86
|
@hp.filter_body(@buf2, @buf << data)
|
|
75
87
|
@input << @buf2
|
|
@@ -79,48 +91,33 @@ module Rainbows::EvCore
|
|
|
79
91
|
if @hp.trailers(@env, @buf << data)
|
|
80
92
|
@input.rewind
|
|
81
93
|
app_call
|
|
94
|
+
else
|
|
95
|
+
want_more
|
|
82
96
|
end
|
|
83
97
|
end
|
|
84
98
|
rescue => e
|
|
85
99
|
handle_error(e)
|
|
86
100
|
end
|
|
87
101
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
client.quit
|
|
95
|
-
|
|
96
|
-
# zip back up the stack
|
|
97
|
-
raise IOError, msg, []
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
def self.new(len, client)
|
|
101
|
-
max = Rainbows.max_bytes
|
|
102
|
-
if len
|
|
103
|
-
if max && (len > max)
|
|
104
|
-
err(client, "Content-Length too big: #{len} > #{max}")
|
|
105
|
-
end
|
|
106
|
-
len <= MAX_BODY ? StringIO.new("") : TmpIO.new
|
|
107
|
-
else
|
|
108
|
-
max ? super(TmpIO.new, client, max) : TmpIO.new
|
|
109
|
-
end
|
|
110
|
-
end
|
|
102
|
+
def err_413(msg)
|
|
103
|
+
write(Rainbows::Const::ERROR_413_RESPONSE)
|
|
104
|
+
quit
|
|
105
|
+
# zip back up the stack
|
|
106
|
+
raise IOError, msg, []
|
|
107
|
+
end
|
|
111
108
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
109
|
+
MAX_BODY = Unicorn::Const::MAX_BODY
|
|
110
|
+
TmpIO = Unicorn::TmpIO
|
|
111
|
+
def mkinput
|
|
112
|
+
max = Rainbows.max_bytes
|
|
113
|
+
len = @hp.content_length
|
|
114
|
+
if len
|
|
115
|
+
if max && (len > max)
|
|
116
|
+
err_413("Content-Length too big: #{len} > #{max}")
|
|
116
117
|
end
|
|
117
|
-
|
|
118
|
+
len <= MAX_BODY ? StringIO.new("") : TmpIO.new
|
|
119
|
+
else
|
|
120
|
+
max ? CapInput.new(TmpIO.new, self) : TmpIO.new
|
|
118
121
|
end
|
|
119
|
-
|
|
120
|
-
def gets; io.gets; end
|
|
121
|
-
def each(&block); io.each(&block); end
|
|
122
|
-
def size; io.size; end
|
|
123
|
-
def rewind; io.rewind; end
|
|
124
|
-
def read(*args); io.read(*args); end
|
|
125
122
|
end
|
|
126
123
|
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# -*- encoding: binary -*-
|
|
2
|
+
# :enddoc:
|
|
3
|
+
class Rainbows::EvCore::CapInput
|
|
4
|
+
def initialize(io, client)
|
|
5
|
+
@io, @client, @bytes_left = io, client, Rainbows.max_bytes
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def <<(buf)
|
|
9
|
+
if (@bytes_left -= buf.size) < 0
|
|
10
|
+
@io.close
|
|
11
|
+
@client.err_413("chunked request body too big")
|
|
12
|
+
end
|
|
13
|
+
@io << buf
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def gets; @io.gets; end
|
|
17
|
+
def each(&block); @io.each(&block); end
|
|
18
|
+
def size; @io.size; end
|
|
19
|
+
def rewind; @io.rewind; end
|
|
20
|
+
def read(*args); @io.read(*args); end
|
|
21
|
+
end
|
data/lib/rainbows/rev/client.rb
CHANGED
|
@@ -16,6 +16,10 @@ module Rainbows
|
|
|
16
16
|
@deferred = nil
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
+
def want_more
|
|
20
|
+
enable unless enabled?
|
|
21
|
+
end
|
|
22
|
+
|
|
19
23
|
def quit
|
|
20
24
|
super
|
|
21
25
|
close if @deferred.nil? && @_write_buffer.empty?
|
|
@@ -143,13 +147,13 @@ module Rainbows
|
|
|
143
147
|
when :close
|
|
144
148
|
close if @_write_buffer.empty?
|
|
145
149
|
when :headers
|
|
146
|
-
if @
|
|
147
|
-
app_call
|
|
148
|
-
else
|
|
150
|
+
if @buf.empty?
|
|
149
151
|
unless enabled?
|
|
150
152
|
enable
|
|
151
153
|
KATO[self] = Time.now
|
|
152
154
|
end
|
|
155
|
+
else
|
|
156
|
+
on_read("")
|
|
153
157
|
end
|
|
154
158
|
end
|
|
155
159
|
rescue => e
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
. ./test-lib.sh
|
|
3
|
+
t_plan 7 "rack.input pipelining test"
|
|
4
|
+
|
|
5
|
+
t_begin "setup and startup" && {
|
|
6
|
+
rainbows_setup $model
|
|
7
|
+
rtmpfiles req
|
|
8
|
+
rainbows -D sha1.ru -c $unicorn_config
|
|
9
|
+
body=hello
|
|
10
|
+
body_size=$(printf $body | wc -c)
|
|
11
|
+
body_sha1=$(printf $body | rsha1)
|
|
12
|
+
rainbows_wait_start
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
t_begin "send pipelined identity requests" && {
|
|
16
|
+
|
|
17
|
+
{
|
|
18
|
+
printf 'PUT / HTTP/1.0\r\n'
|
|
19
|
+
printf 'Connection: keep-alive\r\n'
|
|
20
|
+
printf 'Content-Length: %d\r\n\r\n%s' $body_size $body
|
|
21
|
+
printf 'PUT / HTTP/1.1\r\nHost: example.com\r\n'
|
|
22
|
+
printf 'Content-Length: %d\r\n\r\n%s' $body_size $body
|
|
23
|
+
printf 'PUT / HTTP/1.0\r\n'
|
|
24
|
+
printf 'Content-Length: %d\r\n\r\n%s' $body_size $body
|
|
25
|
+
} > $req
|
|
26
|
+
(
|
|
27
|
+
cat $fifo > $tmp &
|
|
28
|
+
cat $req
|
|
29
|
+
wait
|
|
30
|
+
echo ok > $ok
|
|
31
|
+
) | socat - TCP4:$listen > $fifo
|
|
32
|
+
test x"$(cat $ok)" = xok
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
t_begin "check responses" && {
|
|
36
|
+
dbgcat tmp
|
|
37
|
+
test 3 -eq $(grep $body_sha1 $tmp | wc -l)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
t_begin "send pipelined chunked requests" && {
|
|
41
|
+
|
|
42
|
+
{
|
|
43
|
+
printf 'PUT / HTTP/1.0\r\n'
|
|
44
|
+
printf 'Connection: keep-alive\r\n'
|
|
45
|
+
printf 'Transfer-Encoding: chunked\r\n\r\n'
|
|
46
|
+
printf '%x\r\n%s\r\n0\r\n\r\n' $body_size $body
|
|
47
|
+
printf 'PUT / HTTP/1.1\r\nHost: example.com\r\n'
|
|
48
|
+
printf 'Transfer-Encoding: chunked\r\n\r\n'
|
|
49
|
+
printf '%x\r\n%s\r\n0\r\n\r\n' $body_size $body
|
|
50
|
+
printf 'PUT / HTTP/1.0\r\n'
|
|
51
|
+
printf 'Transfer-Encoding: chunked\r\n\r\n'
|
|
52
|
+
printf '%x\r\n%s\r\n0\r\n\r\n' $body_size $body
|
|
53
|
+
} > $req
|
|
54
|
+
(
|
|
55
|
+
cat $fifo > $tmp &
|
|
56
|
+
cat $req
|
|
57
|
+
wait
|
|
58
|
+
echo ok > $ok
|
|
59
|
+
) | socat - TCP4:$listen > $fifo
|
|
60
|
+
test x"$(cat $ok)" = xok
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
t_begin "check responses" && {
|
|
64
|
+
dbgcat tmp
|
|
65
|
+
test 3 -eq $(grep $body_sha1 $tmp | wc -l)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
t_begin "kill server" && kill $rainbows_pid
|
|
69
|
+
|
|
70
|
+
t_begin "no errors in stderr log" && check_stderr
|
|
71
|
+
|
|
72
|
+
t_done
|
data/t/test_isolate.rb
CHANGED
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rainbows
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
hash:
|
|
4
|
+
hash: 13
|
|
5
5
|
prerelease: false
|
|
6
6
|
segments:
|
|
7
7
|
- 2
|
|
8
8
|
- 0
|
|
9
|
-
-
|
|
10
|
-
version: 2.0.
|
|
9
|
+
- 1
|
|
10
|
+
version: 2.0.1
|
|
11
11
|
platform: ruby
|
|
12
12
|
authors:
|
|
13
13
|
- Rainbows! hackers
|
|
@@ -15,7 +15,7 @@ autorequire:
|
|
|
15
15
|
bindir: bin
|
|
16
16
|
cert_chain: []
|
|
17
17
|
|
|
18
|
-
date: 2010-
|
|
18
|
+
date: 2010-12-03 00:00:00 +00:00
|
|
19
19
|
default_executable:
|
|
20
20
|
dependencies:
|
|
21
21
|
- !ruby/object:Gem::Dependency
|
|
@@ -88,6 +88,7 @@ extra_rdoc_files:
|
|
|
88
88
|
- lib/rainbows/dev_fd_response.rb
|
|
89
89
|
- lib/rainbows/error.rb
|
|
90
90
|
- lib/rainbows/ev_core.rb
|
|
91
|
+
- lib/rainbows/ev_core/cap_input.rb
|
|
91
92
|
- lib/rainbows/event_machine.rb
|
|
92
93
|
- lib/rainbows/event_machine/response_chunk_pipe.rb
|
|
93
94
|
- lib/rainbows/event_machine/response_pipe.rb
|
|
@@ -192,6 +193,7 @@ files:
|
|
|
192
193
|
- lib/rainbows/dev_fd_response.rb
|
|
193
194
|
- lib/rainbows/error.rb
|
|
194
195
|
- lib/rainbows/ev_core.rb
|
|
196
|
+
- lib/rainbows/ev_core/cap_input.rb
|
|
195
197
|
- lib/rainbows/event_machine.rb
|
|
196
198
|
- lib/rainbows/event_machine/response_chunk_pipe.rb
|
|
197
199
|
- lib/rainbows/event_machine/response_pipe.rb
|
|
@@ -341,6 +343,7 @@ files:
|
|
|
341
343
|
- t/t0103-rack-input-limit.sh
|
|
342
344
|
- t/t0104-rack-input-limit-tiny.sh
|
|
343
345
|
- t/t0105-rack-input-limit-bigger.sh
|
|
346
|
+
- t/t0106-rack-input-keepalive.sh
|
|
344
347
|
- t/t0200-async-response.sh
|
|
345
348
|
- t/t0201-async-response-no-autochunk.sh
|
|
346
349
|
- t/t0300-async_sinatra.sh
|