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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 73a1df35604f8a2a57198e315bc7a3f1c0f008d2
4
- data.tar.gz: 7ad6f6bf6464151fcb205a774e68475549f1a73b
3
+ metadata.gz: 100f23910c77a7e45fdb98c841bf13a166eb0b63
4
+ data.tar.gz: ea3c7b2801fa134773bc079f637ccf419b5e6ef5
5
5
  SHA512:
6
- metadata.gz: 2cc36eff407f38c2fe1d768e334455f311672dd0e82f1376fce79151ef4ec07fe1019646087eb24a1d0cb01d5b792cf40da6eb9ac295d58b9e4bb28e9ecb6e99
7
- data.tar.gz: 8b28720a5ff4234b702347cef2e2cc7e5309886ef6b021ef1592cf2d9363c53235209def345329df1903859697f69b4c3afaafa8f946318c708cc8bd34fd205a
6
+ metadata.gz: 7ee178fa9b9b1122a4446353ca6c6f4744aa1589679deef510fe3afeae40f72f66b8ccb96b56476e2e67383b6cd17f10f23c1fedfd81ab588056944e5693fb83
7
+ data.tar.gz: 1f7a89edf6427deeb0f01b26461c744fa56dc22edc5f84d14eacfb48a50618a5622dcc28e67041843d1ff5de2d6b40c4144b580f044e8770f1e453e268ab10a0
data/GIT-VERSION-GEN CHANGED
@@ -5,7 +5,7 @@
5
5
  CONSTANT = "Yahns::VERSION"
6
6
  RVF = "lib/yahns/version.rb"
7
7
  GVF = "GIT-VERSION-FILE"
8
- DEF_VER = "v1.14.0"
8
+ DEF_VER = "v1.14.1"
9
9
  vn = DEF_VER.dup
10
10
 
11
11
  # First see if there is a version file (included in release tarballs),
@@ -131,68 +131,66 @@ def http_response_write(res, opt)
131
131
  term = false
132
132
  hdr_only, chunk_ok = opt
133
133
 
134
- if @hs.headers?
135
- code = status.to_i
136
- hdr_only ||= Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.include?(code)
137
- msg = Rack::Utils::HTTP_STATUS_CODES[code]
138
- buf = "#{response_start}#{msg ? %Q(#{code} #{msg}) : status}\r\n" \
139
- "Date: #{httpdate}\r\n".dup
140
- headers.each do |key, value|
141
- case key
142
- when %r{\ADate\z}i
143
- next
144
- when %r{\AContent-Range\z}i
145
- if %r{\Abytes (\d+)-(\d+)/\d+\z} =~ value
146
- offset = $1.to_i
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
- end
167
- count ||= clen
168
-
169
- if !term && chunk_ok
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
- body = Yahns::ChunkBody.new(body, opt)
172
- buf << "Transfer-Encoding: chunked\r\n".freeze
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
@@ -38,7 +38,7 @@ def thr_init
38
38
  Thread.current[:yahns_queue] = self
39
39
  end
40
40
 
41
- # returns an array of infinitely running threads
41
+ # returns an infinitely running thread
42
42
  def worker_thread(logger, max_events)
43
43
  Thread.new do
44
44
  thr_init
@@ -47,7 +47,7 @@ def thr_init
47
47
  Thread.current[:yahns_queue] = self
48
48
  end
49
49
 
50
- # returns an array of infinitely running threads
50
+ # returns an infinitely running thread
51
51
  def worker_thread(logger, max_events)
52
52
  Thread.new do
53
53
  thr_init
@@ -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
- [ 200, {}, %w(a b c) ]
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
@@ -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
@@ -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.0
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-14 00:00:00.000000000 Z
11
+ date: 2016-12-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: kgio