yahns 1.14.0 → 1.14.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.
- checksums.yaml +4 -4
- data/GIT-VERSION-GEN +1 -1
- data/lib/yahns/http_response.rb +56 -58
- data/lib/yahns/proxy_http_response.rb +1 -1
- data/lib/yahns/queue_epoll.rb +1 -1
- data/lib/yahns/queue_kqueue.rb +1 -1
- data/test/test_auto_chunk.rb +21 -1
- data/test/test_proxy_pass.rb +33 -0
- data/test/test_rack_hijack.rb +6 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 100f23910c77a7e45fdb98c841bf13a166eb0b63
|
4
|
+
data.tar.gz: ea3c7b2801fa134773bc079f637ccf419b5e6ef5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7ee178fa9b9b1122a4446353ca6c6f4744aa1589679deef510fe3afeae40f72f66b8ccb96b56476e2e67383b6cd17f10f23c1fedfd81ab588056944e5693fb83
|
7
|
+
data.tar.gz: 1f7a89edf6427deeb0f01b26461c744fa56dc22edc5f84d14eacfb48a50618a5622dcc28e67041843d1ff5de2d6b40c4144b580f044e8770f1e453e268ab10a0
|
data/GIT-VERSION-GEN
CHANGED
data/lib/yahns/http_response.rb
CHANGED
@@ -131,68 +131,66 @@ def http_response_write(res, opt)
|
|
131
131
|
term = false
|
132
132
|
hdr_only, chunk_ok = opt
|
133
133
|
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
count = $2.to_i - offset + 1
|
148
|
-
end
|
149
|
-
kv_str(buf, key, value)
|
150
|
-
when %r{\AConnection\z}i
|
151
|
-
# allow Rack apps to tell us they want to drop the client
|
152
|
-
alive = false if value =~ /\bclose\b/i
|
153
|
-
when %r{\AContent-Length\z}i
|
154
|
-
term = true
|
155
|
-
clen = value.to_i
|
156
|
-
flags |= MSG_MORE if clen > 0 && !hdr_only
|
157
|
-
kv_str(buf, key, value)
|
158
|
-
when %r{\ATransfer-Encoding\z}i
|
159
|
-
term = true if value =~ /\bchunked\b/i
|
160
|
-
kv_str(buf, key, value)
|
161
|
-
when "rack.hijack"
|
162
|
-
hijack = value
|
163
|
-
else
|
164
|
-
kv_str(buf, key, value)
|
134
|
+
code = status.to_i
|
135
|
+
hdr_only ||= Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.include?(code)
|
136
|
+
msg = Rack::Utils::HTTP_STATUS_CODES[code]
|
137
|
+
buf = "#{response_start}#{msg ? %Q(#{code} #{msg}) : status}\r\n" \
|
138
|
+
"Date: #{httpdate}\r\n".dup
|
139
|
+
headers.each do |key, value|
|
140
|
+
case key
|
141
|
+
when %r{\ADate\z}i
|
142
|
+
next
|
143
|
+
when %r{\AContent-Range\z}i
|
144
|
+
if %r{\Abytes (\d+)-(\d+)/\d+\z} =~ value
|
145
|
+
offset = $1.to_i
|
146
|
+
count = $2.to_i - offset + 1
|
165
147
|
end
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
148
|
+
kv_str(buf, key, value)
|
149
|
+
when %r{\AConnection\z}i
|
150
|
+
# allow Rack apps to tell us they want to drop the client
|
151
|
+
alive = false if value =~ /\bclose\b/i
|
152
|
+
when %r{\AContent-Length\z}i
|
170
153
|
term = true
|
171
|
-
|
172
|
-
|
154
|
+
clen = value.to_i
|
155
|
+
flags |= MSG_MORE if clen > 0 && !hdr_only
|
156
|
+
kv_str(buf, key, value)
|
157
|
+
when %r{\ATransfer-Encoding\z}i
|
158
|
+
term = true if value =~ /\bchunked\b/i
|
159
|
+
kv_str(buf, key, value)
|
160
|
+
when "rack.hijack"
|
161
|
+
hijack = value
|
162
|
+
else
|
163
|
+
kv_str(buf, key, value)
|
173
164
|
end
|
174
|
-
alive &&= term
|
175
|
-
buf << (alive ? "Connection: keep-alive\r\n\r\n".freeze
|
176
|
-
: "Connection: close\r\n\r\n".freeze)
|
177
|
-
case rv = kgio_syssend(buf, flags)
|
178
|
-
when nil # all done, likely
|
179
|
-
buf.clear
|
180
|
-
buf = nil # recycle any memory we used ASAP
|
181
|
-
break
|
182
|
-
when String
|
183
|
-
flags = MSG_DONTWAIT
|
184
|
-
buf = rv # unlikely, hope the skb grows
|
185
|
-
when :wait_writable, :wait_readable # unlikely
|
186
|
-
if self.class.output_buffering
|
187
|
-
alive = hijack ? hijack : alive
|
188
|
-
rv = response_header_blocked(buf, body, alive, offset, count)
|
189
|
-
body = nil # ensure we do not close body in ensure
|
190
|
-
return rv
|
191
|
-
else
|
192
|
-
response_wait_write(rv) or return :close
|
193
|
-
end
|
194
|
-
end while true
|
195
165
|
end
|
166
|
+
count ||= clen
|
167
|
+
|
168
|
+
if !term && chunk_ok && !hdr_only
|
169
|
+
term = true
|
170
|
+
body = Yahns::ChunkBody.new(body, opt)
|
171
|
+
buf << "Transfer-Encoding: chunked\r\n".freeze
|
172
|
+
end
|
173
|
+
alive &&= (term || hdr_only)
|
174
|
+
buf << (alive ? "Connection: keep-alive\r\n\r\n".freeze
|
175
|
+
: "Connection: close\r\n\r\n".freeze)
|
176
|
+
case rv = kgio_syssend(buf, flags)
|
177
|
+
when nil # all done, likely
|
178
|
+
buf.clear
|
179
|
+
buf = nil # recycle any memory we used ASAP
|
180
|
+
break
|
181
|
+
when String
|
182
|
+
flags = MSG_DONTWAIT
|
183
|
+
buf = rv # unlikely, hope the skb grows
|
184
|
+
when :wait_writable, :wait_readable # unlikely
|
185
|
+
if self.class.output_buffering
|
186
|
+
alive = hijack ? hijack : alive
|
187
|
+
rv = response_header_blocked(buf, body, alive, offset, count)
|
188
|
+
body = nil # ensure we do not close body in ensure
|
189
|
+
return rv
|
190
|
+
else
|
191
|
+
response_wait_write(rv) or return :close
|
192
|
+
end
|
193
|
+
end while @hs.headers?
|
196
194
|
|
197
195
|
return response_hijacked(hijack) if hijack
|
198
196
|
return http_response_done(alive) if hdr_only
|
@@ -120,7 +120,7 @@ def proxy_res_headers(res, req_res)
|
|
120
120
|
|
121
121
|
# chunk the response ourselves if the client supports it,
|
122
122
|
# but the backend does not terminate properly
|
123
|
-
if alive && ! term
|
123
|
+
if alive && ! term && have_body
|
124
124
|
if env['HTTP_VERSION'] == 'HTTP/1.1'.freeze
|
125
125
|
res << "Transfer-Encoding: chunked\r\n".freeze
|
126
126
|
else # we can't persist HTTP/1.0 and HTTP/0.9 w/o Content-Length
|
data/lib/yahns/queue_epoll.rb
CHANGED
data/lib/yahns/queue_kqueue.rb
CHANGED
data/test/test_auto_chunk.rb
CHANGED
@@ -18,7 +18,12 @@ def test_auto_head
|
|
18
18
|
app = Rack::Builder.new do
|
19
19
|
use Rack::ContentType, "text/plain"
|
20
20
|
run(lambda do |env|
|
21
|
-
[
|
21
|
+
case env['PATH_INFO']
|
22
|
+
when '/204'
|
23
|
+
[ 204, {}, [] ]
|
24
|
+
else
|
25
|
+
[ 200, {}, %w(a b c) ]
|
26
|
+
end
|
22
27
|
end)
|
23
28
|
end
|
24
29
|
app(:rack, app) { listen "#{host}:#{port}" }
|
@@ -50,6 +55,21 @@ def test_auto_head
|
|
50
55
|
assert_equal 200, res.code.to_i
|
51
56
|
assert_equal 'abc', res.body
|
52
57
|
end
|
58
|
+
|
59
|
+
s = TCPSocket.new(host, port)
|
60
|
+
s.write("GET /204 HTTP/1.1\r\nHost: example.com\r\n\r\n")
|
61
|
+
buf = s.readpartial(1024)
|
62
|
+
assert_match %r{\r\n\r\n\z}, buf
|
63
|
+
refute_match %r{^Transfer-Encoding}i, buf
|
64
|
+
assert_match %r{^Connection: keep-alive\r\n}, buf
|
65
|
+
assert_nil IO.select([s], nil, nil, 1), 'connection persists..'
|
66
|
+
|
67
|
+
# maek sure another on the same connection works
|
68
|
+
s.write("GET / HTTP/1.1\r\nHost: example.com\r\n\r\n")
|
69
|
+
buf = s.readpartial(1024)
|
70
|
+
assert_match %r{\AHTTP/1\.1 200}, buf
|
71
|
+
assert_match(%r{^Transfer-Encoding: chunked\r\n}, buf)
|
72
|
+
s.close
|
53
73
|
ensure
|
54
74
|
quit_wait(pid)
|
55
75
|
end
|
data/test/test_proxy_pass.rb
CHANGED
@@ -154,6 +154,9 @@ def chunky.each
|
|
154
154
|
env['rack.hijack'].call.close
|
155
155
|
# should not be seen:
|
156
156
|
[ 123, [ %w(Content-Type text/html), %w(Content-Length 0) ], [] ]
|
157
|
+
when '/204'
|
158
|
+
buf = env['rack.input'].read # drain
|
159
|
+
[ 204, {}, [] ]
|
157
160
|
else
|
158
161
|
buf = env['rack.input'].read
|
159
162
|
[ 201, {
|
@@ -271,6 +274,7 @@ def test_proxy_pass
|
|
271
274
|
end
|
272
275
|
end
|
273
276
|
|
277
|
+
check_204_on_put(host, port)
|
274
278
|
check_forbidden_put(host, port)
|
275
279
|
check_eof_body(host, port)
|
276
280
|
check_pipelining(host, port)
|
@@ -639,4 +643,33 @@ def check_forbidden_put(host, port)
|
|
639
643
|
ensure
|
640
644
|
to_close.each(&:close)
|
641
645
|
end
|
646
|
+
|
647
|
+
def check_204_on_put(host, port)
|
648
|
+
s = TCPSocket.new(host, port)
|
649
|
+
s.write("PUT /204 HTTP/1.1\r\nHost: example.com\r\n" \
|
650
|
+
"Content-Length: 11\r\n" \
|
651
|
+
"Content-Type: application/octet-stream\r\n" \
|
652
|
+
"\r\nhello worldPUT")
|
653
|
+
buf = s.readpartial(1024)
|
654
|
+
assert_match %r{\AHTTP/1\.1 204}, buf
|
655
|
+
assert_match %r{\r\n\r\n\z}, buf
|
656
|
+
refute_match %r{^Transfer-Encoding}i, buf
|
657
|
+
refute_match %r{^Content-Length}i, buf
|
658
|
+
assert_match %r{^Connection: keep-alive\r\n}, buf
|
659
|
+
assert_nil IO.select([s], nil, nil, 1), 'connection persists..'
|
660
|
+
|
661
|
+
# make sure another on the same connection works
|
662
|
+
s.write(" / HTTP/1.1\r\nHost: example.com\r\n" \
|
663
|
+
"Content-Length: 11\r\n" \
|
664
|
+
"Content-Type: application/octet-stream\r\n" \
|
665
|
+
"\r\nhello world")
|
666
|
+
buf = s.readpartial(1024)
|
667
|
+
assert_match %r{\r\n\r\nhello world\z}, buf
|
668
|
+
assert_match %r{\AHTTP/1\.1 201}, buf
|
669
|
+
assert_match(%r{^Content-Length: 11\r\n}, buf)
|
670
|
+
assert_match %r{^Connection: keep-alive\r\n}, buf
|
671
|
+
assert_nil IO.select([s], nil, nil, 1), 'connection persists..'
|
672
|
+
ensure
|
673
|
+
s.close if s
|
674
|
+
end
|
642
675
|
end
|
data/test/test_rack_hijack.rb
CHANGED
@@ -86,6 +86,12 @@ def test_hijack
|
|
86
86
|
assert_equal "rack.input contents: BLAH", res.body
|
87
87
|
assert_equal 201, res.code.to_i
|
88
88
|
assert_equal "1.0", res.http_version
|
89
|
+
|
90
|
+
# ancient "HTTP/0.9"
|
91
|
+
c = get_tcp_client(host, port)
|
92
|
+
c.write("GET /hijack_res\r\n\r\n")
|
93
|
+
res = Timeout.timeout(30) { c.read }
|
94
|
+
assert_equal 'response.hijacked', res
|
89
95
|
ensure
|
90
96
|
quit_wait(pid)
|
91
97
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: yahns
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.14.
|
4
|
+
version: 1.14.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- yahns hackers
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-12-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: kgio
|