http 0.9.4 → 0.9.5

Sign up to get free protection for your applications and to get access to all the features.
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: