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 +4 -4
- data/CHANGES.md +5 -0
- data/lib/http/client.rb +33 -11
- data/lib/http/version.rb +1 -1
- data/spec/http/client_spec.rb +64 -5
- metadata +3 -29
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dbf54512a5beb049b061b0ba6fa9cff6599fdd03
|
4
|
+
data.tar.gz: 27cd308a2ca24d95b09ea54cffc47ede483b7842
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9f51593e3ecef81acc55ca3941b978c63011979ab2933409f57fe3272ae061553a32d72abfa219946ee0ba6d465157159b7e7fddcac29b4e9ebda3d1fa096fff
|
7
|
+
data.tar.gz: fd396a2f0ea79ee4014844c71de5bf97cb40bd60feef0e733b51adf16f76be3dadbbde7a58a09025ba6e641abc0676f5c66887dc649f0a415c54934f9eeabbec
|
data/CHANGES.md
CHANGED
data/lib/http/client.rb
CHANGED
@@ -55,11 +55,7 @@ module HTTP
|
|
55
55
|
|
56
56
|
req.stream @socket
|
57
57
|
|
58
|
-
|
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
|
-
|
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
|
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 =
|
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
data/spec/http/client_spec.rb
CHANGED
@@ -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
|
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(
|
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(
|
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(
|
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(
|
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.
|
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-
|
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:
|