http 0.6.2 → 0.6.3

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of http might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: eaab2ce76635211389fd9480ab6bde7e5dff1e3e
4
- data.tar.gz: 7a4769b42117b5fcca8163bbfcd59e2bcb0baccb
3
+ metadata.gz: dbf54512a5beb049b061b0ba6fa9cff6599fdd03
4
+ data.tar.gz: 27cd308a2ca24d95b09ea54cffc47ede483b7842
5
5
  SHA512:
6
- metadata.gz: 2caf7623ed59f9d1bc978928e6174cd84f512acc1f50f9b70df78607eb4fca26c12b9a4899c61483fa86f32630c08a5218e5aeef4b669847de8c54d8036c76f4
7
- data.tar.gz: e91ae392e1bf3b142567289e536a59742a35fac2c774c0129a22019cd06e1805adc219e2439cfc39b2f4eb33c7899e0a37037b0ec9732cc2fdeff1331f9ed178
6
+ metadata.gz: 9f51593e3ecef81acc55ca3941b978c63011979ab2933409f57fe3272ae061553a32d72abfa219946ee0ba6d465157159b7e7fddcac29b4e9ebda3d1fa096fff
7
+ data.tar.gz: fd396a2f0ea79ee4014844c71de5bf97cb40bd60feef0e733b51adf16f76be3dadbbde7a58a09025ba6e641abc0676f5c66887dc649f0a415c54934f9eeabbec
data/CHANGES.md CHANGED
@@ -1,3 +1,8 @@
1
+ 0.6.3 (2014-11-14)
2
+ ------------------
3
+
4
+ * Backported EOF fix from master branch. See #166. (@ixti)
5
+
1
6
  0.6.2 (2014-08-06)
2
7
  ------------------
3
8
 
data/lib/http/client.rb CHANGED
@@ -55,11 +55,7 @@ module HTTP
55
55
 
56
56
  req.stream @socket
57
57
 
58
- begin
59
- read_more BUFFER_SIZE until @parser.headers
60
- rescue IOError, Errno::ECONNRESET, Errno::EPIPE => ex
61
- raise IOError, "problem making HTTP request: #{ex}"
62
- end
58
+ read_headers!
63
59
 
64
60
  body = Response::Body.new(self)
65
61
  res = Response.new(@parser.status_code, @parser.http_version, @parser.headers, body, uri)
@@ -73,10 +69,16 @@ module HTTP
73
69
  def readpartial(size = BUFFER_SIZE)
74
70
  return unless @socket
75
71
 
76
- read_more size
72
+ begin
73
+ read_more size
74
+ finished = @parser.finished?
75
+ rescue EOFError
76
+ finished = true
77
+ end
78
+
77
79
  chunk = @parser.chunk
78
80
 
79
- finish_response if @parser.finished?
81
+ finish_response if finished
80
82
 
81
83
  chunk.to_s
82
84
  end
@@ -95,7 +97,7 @@ module HTTP
95
97
 
96
98
  # Merges query params if needed
97
99
  def make_request_uri(uri, options)
98
- uri = URI uri.to_s unless uri.is_a? URI
100
+ uri = normalize_uri uri
99
101
 
100
102
  if options.params && !options.params.empty?
101
103
  params = CGI.parse(uri.query.to_s).merge(options.params || {})
@@ -105,6 +107,21 @@ module HTTP
105
107
  uri
106
108
  end
107
109
 
110
+ # Normalize URI
111
+ #
112
+ # @param [#to_s] uri
113
+ # @return [URI]
114
+ def normalize_uri(uri)
115
+ uri = URI uri.to_s
116
+
117
+ # Some proxies (seen on WEBRick) fail if URL has
118
+ # empty path (e.g. `http://example.com`) while it's RFC-complaint:
119
+ # http://tools.ietf.org/html/rfc1738#section-3.1
120
+ uri.path = '/' if uri.path.empty?
121
+
122
+ uri
123
+ end
124
+
108
125
  # Create the request body object to send
109
126
  def make_request_body(opts, headers)
110
127
  if opts.body
@@ -118,6 +135,14 @@ module HTTP
118
135
  end
119
136
  end
120
137
 
138
+ # Reads data from socket up until headers
139
+ def read_headers!
140
+ read_more BUFFER_SIZE until @parser.headers
141
+ rescue IOError, Errno::ECONNRESET, Errno::EPIPE => ex
142
+ return if ex.is_a?(EOFError) && @parser.headers
143
+ raise IOError, "problem making HTTP request: #{ex}"
144
+ end
145
+
121
146
  # Callback for when we've reached the end of a response
122
147
  def finish_response
123
148
  @socket.close if @socket && !@socket.closed?
@@ -129,9 +154,6 @@ module HTTP
129
154
  # Feeds some more data into parser
130
155
  def read_more(size)
131
156
  @parser << @socket.readpartial(size) unless @parser.finished?
132
- true
133
- rescue EOFError
134
- false
135
157
  end
136
158
  end
137
159
  end
data/lib/http/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module HTTP
2
- VERSION = '0.6.2'
2
+ VERSION = '0.6.3'
3
3
  end
@@ -1,6 +1,8 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe HTTP::Client do
4
+ let(:test_endpoint) { "http://127.0.0.1:#{ExampleService::PORT}" }
5
+
4
6
  StubbedClient = Class.new(HTTP::Client) do
5
7
  def perform(request, options)
6
8
  stubs.fetch(request.uri.to_s) { super(request, options) }
@@ -148,23 +150,80 @@ describe HTTP::Client do
148
150
  it 'calls finish_response before actual performance' do
149
151
  TCPSocket.stub(:open) { throw :halt }
150
152
  expect(client).to receive(:finish_response)
151
- catch(:halt) { client.head "http://127.0.0.1:#{ExampleService::PORT}/" }
153
+ catch(:halt) { client.head test_endpoint }
152
154
  end
153
155
 
154
156
  it 'calls finish_response once body was fully flushed' do
155
157
  expect(client).to receive(:finish_response).twice.and_call_original
156
- client.get("http://127.0.0.1:#{ExampleService::PORT}/").to_s
158
+ client.get(test_endpoint).to_s
157
159
  end
158
160
 
159
161
  context 'with HEAD request' do
160
162
  it 'does not iterates through body' do
161
163
  expect(client).to_not receive(:readpartial)
162
- client.head("http://127.0.0.1:#{ExampleService::PORT}/")
164
+ client.head(test_endpoint)
163
165
  end
164
166
 
165
167
  it 'finishes response after headers were received' do
166
168
  expect(client).to receive(:finish_response).twice.and_call_original
167
- client.head("http://127.0.0.1:#{ExampleService::PORT}/")
169
+ client.head(test_endpoint)
170
+ end
171
+ end
172
+
173
+ context 'when server closes connection unexpectedly' do
174
+ before do
175
+ socket_spy = double
176
+
177
+ allow(socket_spy).to receive(:close) { nil }
178
+ allow(socket_spy).to receive(:closed?) { true }
179
+ allow(socket_spy).to receive(:readpartial) { chunks.shift.call }
180
+ allow(socket_spy).to receive(:<<) { nil }
181
+
182
+ allow(TCPSocket).to receive(:open) { socket_spy }
183
+ end
184
+
185
+ context 'during headers reading' do
186
+ let :chunks do
187
+ [
188
+ proc { "HTTP/1.1 200 OK\r\n" },
189
+ proc { "Content-Type: text/html\r" },
190
+ proc { fail EOFError }
191
+ ]
192
+ end
193
+
194
+ it 'raises IOError' do
195
+ expect { client.get test_endpoint }.to raise_error IOError
196
+ end
197
+ end
198
+
199
+ context 'after headers were flushed' do
200
+ let :chunks do
201
+ [
202
+ proc { "HTTP/1.1 200 OK\r\n" },
203
+ proc { "Content-Type: text/html\r\n\r\n" },
204
+ proc { 'unexpected end of f' },
205
+ proc { fail EOFError }
206
+ ]
207
+ end
208
+
209
+ it 'reads partially arrived body' do
210
+ res = client.get(test_endpoint).to_s
211
+ expect(res).to eq 'unexpected end of f'
212
+ end
213
+ end
214
+
215
+ context 'when body and headers were flushed in one chunk' do
216
+ let :chunks do
217
+ [
218
+ proc { "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\nunexpected end of f" },
219
+ proc { fail EOFError }
220
+ ]
221
+ end
222
+
223
+ it 'reads partially arrived body' do
224
+ res = client.get(test_endpoint).to_s
225
+ expect(res).to eq 'unexpected end of f'
226
+ end
168
227
  end
169
228
  end
170
229
 
@@ -194,7 +253,7 @@ describe HTTP::Client do
194
253
  end
195
254
 
196
255
  it 'properly reads body' do
197
- body = client.get("http://127.0.0.1:#{ExampleService::PORT}/").to_s
256
+ body = client.get(test_endpoint).to_s
198
257
  expect(body).to eq '<!doctype html>'
199
258
  end
200
259
  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.6.2
4
+ version: 0.6.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tony
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-08-06 00:00:00.000000000 Z
12
+ date: 2014-11-14 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: http_parser.rb
@@ -135,31 +135,5 @@ rubygems_version: 2.2.2
135
135
  signing_key:
136
136
  specification_version: 4
137
137
  summary: HTTP should be easy
138
- test_files:
139
- - spec/http/authorization_header/basic_auth_spec.rb
140
- - spec/http/authorization_header/bearer_token_spec.rb
141
- - spec/http/authorization_header_spec.rb
142
- - spec/http/backports/base64_spec.rb
143
- - spec/http/backports/uri_spec.rb
144
- - spec/http/client_spec.rb
145
- - spec/http/content_type_spec.rb
146
- - spec/http/headers/mixin_spec.rb
147
- - spec/http/headers_spec.rb
148
- - spec/http/options/body_spec.rb
149
- - spec/http/options/form_spec.rb
150
- - spec/http/options/headers_spec.rb
151
- - spec/http/options/json_spec.rb
152
- - spec/http/options/merge_spec.rb
153
- - spec/http/options/new_spec.rb
154
- - spec/http/options/proxy_spec.rb
155
- - spec/http/options_spec.rb
156
- - spec/http/redirector_spec.rb
157
- - spec/http/request/writer_spec.rb
158
- - spec/http/request_spec.rb
159
- - spec/http/response/body_spec.rb
160
- - spec/http/response_spec.rb
161
- - spec/http_spec.rb
162
- - spec/spec_helper.rb
163
- - spec/support/example_server.rb
164
- - spec/support/proxy_server.rb
138
+ test_files: []
165
139
  has_rdoc: