http 0.9.4 → 0.9.5

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: 2cf4cc1f50d48b38982e5b7d22cce064944076ca
4
- data.tar.gz: c3528a21ae58c9ea4ce9e8ea6c8c29c8160c74e1
3
+ metadata.gz: 47725ac8f768c31d62281f8c11fe9b4d68d0cfb2
4
+ data.tar.gz: 09c4bdf669c287c16de5e908ee4030639300111f
5
5
  SHA512:
6
- metadata.gz: 3fbfc83dc70d26f03ceefba22ffed7ad9a235c4811dc05342c0f51d1c968af020f990bc31d8dc713659a1cd952350169a25f575695e684cc7b1242ab5394f186
7
- data.tar.gz: 631b31981f832f3c22bf6c175345cf68d7a9c0fdac2cb8477c28ba0547bffe0e7dac4218dbdf83242132deb54a867d9d7637a1483ec39107569fa0f0af393aec
6
+ metadata.gz: 00fe6c13bc759adc589452d22cc263d7b3c12ea812fe4eada6a43080f5f06411d4d133ed314e4a71f958c3b1121631c197a15482e54813c469a2300ee7dd640d
7
+ data.tar.gz: 8ea1c8fbe444a0a0f59bc9dc262d3401dff1c0cb45957d166ab0a382bc4b9aeaaf4c0dcc8855cff5f5fa40efd9bf627d5211c264c7315fc96f56a68b410f4aa9
data/CHANGES.md CHANGED
@@ -1,3 +1,8 @@
1
+ ## 0.9.5 (2015-09-06)
2
+
3
+ * Fixed infinite hang/timeout when a request contained more than ~16,363 bytes.
4
+ See #252. (@zanker)
5
+
1
6
  ## 0.9.4 (2015-08-26)
2
7
 
3
8
  * Fixes regression when body streaming was failing on some URIs.
@@ -12,6 +12,9 @@ module HTTP
12
12
  # Chunked transfer encoding
13
13
  CHUNKED = "chunked".freeze
14
14
 
15
+ # End of a chunked transfer
16
+ CHUNKED_END = "#{ZERO}#{CRLF}#{CRLF}".freeze
17
+
15
18
  # Types valid to be used as body source
16
19
  VALID_BODY_TYPES = [String, NilClass, Enumerable]
17
20
 
@@ -40,7 +43,7 @@ module HTTP
40
43
  # Send headers needed to connect through proxy
41
44
  def connect_through_proxy
42
45
  add_headers
43
- @socket << join_headers
46
+ write(join_headers)
44
47
  end
45
48
 
46
49
  # Adds the headers to the header array for the given request body we are working
@@ -65,24 +68,35 @@ module HTTP
65
68
  add_headers
66
69
  add_body_type_headers
67
70
 
68
- @socket << join_headers
71
+ write(join_headers)
69
72
  end
70
73
 
71
74
  def send_request_body
72
75
  if @body.is_a?(String)
73
- @socket << @body
76
+ write(@body)
74
77
  elsif @body.is_a?(Enumerable)
75
78
  @body.each do |chunk|
76
- @socket << chunk.bytesize.to_s(16) << CRLF
77
- @socket << chunk << CRLF
79
+ write(chunk.bytesize.to_s(16) << CRLF)
80
+ write(chunk << CRLF)
78
81
  end
79
82
 
80
- @socket << ZERO << CRLF << CRLF
83
+ write(CHUNKED_END)
81
84
  end
82
85
  end
83
86
 
84
87
  private
85
88
 
89
+ def write(data)
90
+ while data.present?
91
+ length = @socket.write(data)
92
+ if data.length > length
93
+ data = data[length..-1]
94
+ else
95
+ break
96
+ end
97
+ end
98
+ end
99
+
86
100
  def validate_body_type!
87
101
  return if VALID_BODY_TYPES.any? { |type| @body.is_a? type }
88
102
  fail RequestError, "body of wrong type: #{@body.class}"
@@ -61,7 +61,7 @@ module HTTP
61
61
  reset_timer
62
62
 
63
63
  begin
64
- socket.write_nonblock(data)
64
+ return socket.write_nonblock(data)
65
65
  rescue IO::WaitWritable
66
66
  IO.select(nil, [socket], nil, time_left)
67
67
  log_time
@@ -97,7 +97,7 @@ module HTTP
97
97
 
98
98
  loop do
99
99
  result = socket.write_nonblock(data, :exception => false)
100
- break unless result == :wait_writable
100
+ return result unless result == :wait_writable
101
101
 
102
102
  IO.select(nil, [socket], nil, time_left)
103
103
  log_time
@@ -45,7 +45,7 @@ module HTTP
45
45
 
46
46
  # Write to the socket
47
47
  def write(data)
48
- @socket << data
48
+ @socket.write(data)
49
49
  end
50
50
  alias_method :<<, :write
51
51
 
@@ -75,7 +75,7 @@ module HTTP
75
75
  def write(data)
76
76
  loop do
77
77
  result = socket.write_nonblock(data, :exception => false)
78
- break unless result == :wait_writable
78
+ return result unless result == :wait_writable
79
79
 
80
80
  unless IO.select(nil, [socket], nil, write_timeout)
81
81
  fail TimeoutError, "Read timed out after #{write_timeout} seconds"
data/lib/http/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module HTTP
2
- VERSION = "0.9.4".freeze
2
+ VERSION = "0.9.5".freeze
3
3
  end
@@ -267,8 +267,8 @@ RSpec.describe HTTP::Client do
267
267
 
268
268
  allow(socket_spy).to receive(:close) { nil }
269
269
  allow(socket_spy).to receive(:closed?) { true }
270
- allow(socket_spy).to receive(:readpartial) { chunks.shift }
271
- allow(socket_spy).to receive(:<<) { nil }
270
+ allow(socket_spy).to receive(:readpartial) { chunks[0] }
271
+ allow(socket_spy).to receive(:write) { chunks[0].length }
272
272
 
273
273
  allow(TCPSocket).to receive(:open) { socket_spy }
274
274
  end
@@ -44,6 +44,32 @@ RSpec.describe HTTP do
44
44
  expect(response.to_s.include?("json")).to be true
45
45
  end
46
46
  end
47
+
48
+ context "with a large request body" do
49
+ %w(global null per_operation).each do |timeout|
50
+ context "with a #{timeout} timeout" do
51
+ [16_000, 16_500, 17_000, 34_000, 68_000].each do |size|
52
+ [0, rand(0..100), rand(100..1000)].each do |fuzzer|
53
+ context "with a #{size} body and #{fuzzer} of fuzzing" do
54
+ let(:client) { HTTP.timeout(timeout, :read => 2, :write => 2, :connect => 2) }
55
+
56
+ let(:characters) { ("A".."Z").to_a }
57
+ let(:request_body) do
58
+ (size + fuzzer).times.map { |i| characters[i % characters.length] }.join
59
+ end
60
+
61
+ it "returns a large body" do
62
+ response = client.post("#{dummy.endpoint}/echo-body", :body => request_body)
63
+
64
+ expect(response.body.to_s).to eq(request_body)
65
+ expect(response.headers["Content-Length"].to_i).to eq(request_body.length)
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
47
73
  end
48
74
 
49
75
  describe ".via" do
@@ -133,5 +133,10 @@ class DummyServer < WEBrick::HTTPServer
133
133
  res["Set-Cookie"] = "foo=bar"
134
134
  res.body = req.cookies.map { |c| [c.name, c.value].join ": " }.join("\n")
135
135
  end
136
+
137
+ post "/echo-body" do |req, res|
138
+ res.status = 200
139
+ res.body = req.body
140
+ end
136
141
  end
137
142
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: http
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.4
4
+ version: 0.9.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tony Arcieri
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2015-08-25 00:00:00.000000000 Z
14
+ date: 2015-09-06 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: http_parser.rb
@@ -184,9 +184,40 @@ required_rubygems_version: !ruby/object:Gem::Requirement
184
184
  version: '0'
185
185
  requirements: []
186
186
  rubyforge_project:
187
- rubygems_version: 2.2.3
187
+ rubygems_version: 2.4.6
188
188
  signing_key:
189
189
  specification_version: 4
190
190
  summary: HTTP should be easy
191
- test_files: []
191
+ test_files:
192
+ - spec/lib/http/client_spec.rb
193
+ - spec/lib/http/content_type_spec.rb
194
+ - spec/lib/http/headers/mixin_spec.rb
195
+ - spec/lib/http/headers_spec.rb
196
+ - spec/lib/http/options/body_spec.rb
197
+ - spec/lib/http/options/form_spec.rb
198
+ - spec/lib/http/options/headers_spec.rb
199
+ - spec/lib/http/options/json_spec.rb
200
+ - spec/lib/http/options/merge_spec.rb
201
+ - spec/lib/http/options/new_spec.rb
202
+ - spec/lib/http/options/proxy_spec.rb
203
+ - spec/lib/http/options_spec.rb
204
+ - spec/lib/http/redirector_spec.rb
205
+ - spec/lib/http/request/writer_spec.rb
206
+ - spec/lib/http/request_spec.rb
207
+ - spec/lib/http/response/body_spec.rb
208
+ - spec/lib/http/response/status_spec.rb
209
+ - spec/lib/http/response_spec.rb
210
+ - spec/lib/http_spec.rb
211
+ - spec/regression_specs.rb
212
+ - spec/spec_helper.rb
213
+ - spec/support/black_hole.rb
214
+ - spec/support/capture_warning.rb
215
+ - spec/support/connection_reuse_shared.rb
216
+ - spec/support/dummy_server.rb
217
+ - spec/support/dummy_server/servlet.rb
218
+ - spec/support/http_handling_shared.rb
219
+ - spec/support/proxy_server.rb
220
+ - spec/support/servers/config.rb
221
+ - spec/support/servers/runner.rb
222
+ - spec/support/ssl_helper.rb
192
223
  has_rdoc: