http 0.9.8 → 1.0.0
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 +4 -4
- data/.rubocop.yml +1 -1
- data/.travis.yml +1 -0
- data/CHANGES.md +143 -92
- data/Gemfile +4 -4
- data/README.md +8 -27
- data/lib/http/chainable.rb +13 -30
- data/lib/http/client.rb +17 -12
- data/lib/http/connection.rb +10 -7
- data/lib/http/errors.rb +3 -0
- data/lib/http/headers.rb +0 -3
- data/lib/http/options.rb +9 -12
- data/lib/http/request/writer.rb +14 -12
- data/lib/http/request.rb +23 -14
- data/lib/http/response/body.rb +7 -6
- data/lib/http/response/parser.rb +2 -1
- data/lib/http/response/status.rb +1 -3
- data/lib/http/response.rb +31 -28
- data/lib/http/timeout/global.rb +2 -1
- data/lib/http/timeout/null.rb +2 -1
- data/lib/http/timeout/per_operation.rb +2 -1
- data/lib/http/version.rb +1 -1
- data/lib/http.rb +0 -2
- data/logo.png +0 -0
- data/spec/lib/http/client_spec.rb +25 -16
- data/spec/lib/http/options/merge_spec.rb +3 -1
- data/spec/lib/http/options_spec.rb +2 -3
- data/spec/lib/http/redirector_spec.rb +39 -34
- data/spec/lib/http/request/writer_spec.rb +3 -3
- data/spec/lib/http/request_spec.rb +41 -7
- data/spec/lib/http/response/body_spec.rb +1 -1
- data/spec/lib/http/response/status_spec.rb +3 -3
- data/spec/lib/http/response_spec.rb +10 -1
- data/spec/lib/http_spec.rb +66 -7
- data/spec/spec_helper.rb +2 -2
- data/spec/support/connection_reuse_shared.rb +1 -1
- data/spec/support/dummy_server/servlet.rb +7 -0
- data/spec/support/http_handling_shared.rb +7 -1
- metadata +3 -4
- data/examples/parallel_requests_with_celluloid.rb +0 -38
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
RSpec.describe HTTP::Redirector do
|
|
2
2
|
def simple_response(status, body = "", headers = {})
|
|
3
|
-
HTTP::Response.new(
|
|
3
|
+
HTTP::Response.new(
|
|
4
|
+
:status => status,
|
|
5
|
+
:version => "1.1",
|
|
6
|
+
:headers => headers,
|
|
7
|
+
:body => body
|
|
8
|
+
)
|
|
4
9
|
end
|
|
5
10
|
|
|
6
11
|
def redirect_response(status, location)
|
|
@@ -30,7 +35,7 @@ RSpec.describe HTTP::Redirector do
|
|
|
30
35
|
let(:redirector) { described_class.new options }
|
|
31
36
|
|
|
32
37
|
it "fails with TooManyRedirectsError if max hops reached" do
|
|
33
|
-
req = HTTP::Request.new :head, "http://example.com"
|
|
38
|
+
req = HTTP::Request.new :verb => :head, :uri => "http://example.com"
|
|
34
39
|
res = proc { |prev_req| redirect_response(301, "#{prev_req.uri}/1") }
|
|
35
40
|
|
|
36
41
|
expect { redirector.perform(req, res.call(req), &res) }.
|
|
@@ -38,7 +43,7 @@ RSpec.describe HTTP::Redirector do
|
|
|
38
43
|
end
|
|
39
44
|
|
|
40
45
|
it "fails with EndlessRedirectError if endless loop detected" do
|
|
41
|
-
req = HTTP::Request.new :head, "http://example.com"
|
|
46
|
+
req = HTTP::Request.new :verb => :head, :uri => "http://example.com"
|
|
42
47
|
res = redirect_response(301, req.uri)
|
|
43
48
|
|
|
44
49
|
expect { redirector.perform(req, res) { res } }.
|
|
@@ -46,7 +51,7 @@ RSpec.describe HTTP::Redirector do
|
|
|
46
51
|
end
|
|
47
52
|
|
|
48
53
|
it "fails with StateError if there were no Location header" do
|
|
49
|
-
req = HTTP::Request.new :head, "http://example.com"
|
|
54
|
+
req = HTTP::Request.new :verb => :head, :uri => "http://example.com"
|
|
50
55
|
res = simple_response(301)
|
|
51
56
|
|
|
52
57
|
expect { |b| redirector.perform(req, res, &b) }.
|
|
@@ -54,7 +59,7 @@ RSpec.describe HTTP::Redirector do
|
|
|
54
59
|
end
|
|
55
60
|
|
|
56
61
|
it "returns first non-redirect response" do
|
|
57
|
-
req = HTTP::Request.new :head, "http://example.com"
|
|
62
|
+
req = HTTP::Request.new :verb => :head, :uri => "http://example.com"
|
|
58
63
|
hops = [
|
|
59
64
|
redirect_response(301, "http://example.com/1"),
|
|
60
65
|
redirect_response(301, "http://example.com/2"),
|
|
@@ -73,7 +78,7 @@ RSpec.describe HTTP::Redirector do
|
|
|
73
78
|
let(:options) { {:strict => true} }
|
|
74
79
|
|
|
75
80
|
it "it follows with original verb if it's safe" do
|
|
76
|
-
req = HTTP::Request.new :head, "http://example.com"
|
|
81
|
+
req = HTTP::Request.new :verb => :head, :uri => "http://example.com"
|
|
77
82
|
res = redirect_response 300, "http://example.com/1"
|
|
78
83
|
|
|
79
84
|
redirector.perform(req, res) do |prev_req, _|
|
|
@@ -83,7 +88,7 @@ RSpec.describe HTTP::Redirector do
|
|
|
83
88
|
end
|
|
84
89
|
|
|
85
90
|
it "raises StateError if original request was PUT" do
|
|
86
|
-
req = HTTP::Request.new :put, "http://example.com"
|
|
91
|
+
req = HTTP::Request.new :verb => :put, :uri => "http://example.com"
|
|
87
92
|
res = redirect_response 300, "http://example.com/1"
|
|
88
93
|
|
|
89
94
|
expect { redirector.perform(req, res) { simple_response 200 } }.
|
|
@@ -91,7 +96,7 @@ RSpec.describe HTTP::Redirector do
|
|
|
91
96
|
end
|
|
92
97
|
|
|
93
98
|
it "raises StateError if original request was POST" do
|
|
94
|
-
req = HTTP::Request.new :post, "http://example.com"
|
|
99
|
+
req = HTTP::Request.new :verb => :post, :uri => "http://example.com"
|
|
95
100
|
res = redirect_response 300, "http://example.com/1"
|
|
96
101
|
|
|
97
102
|
expect { redirector.perform(req, res) { simple_response 200 } }.
|
|
@@ -99,7 +104,7 @@ RSpec.describe HTTP::Redirector do
|
|
|
99
104
|
end
|
|
100
105
|
|
|
101
106
|
it "raises StateError if original request was DELETE" do
|
|
102
|
-
req = HTTP::Request.new :delete, "http://example.com"
|
|
107
|
+
req = HTTP::Request.new :verb => :delete, :uri => "http://example.com"
|
|
103
108
|
res = redirect_response 300, "http://example.com/1"
|
|
104
109
|
|
|
105
110
|
expect { redirector.perform(req, res) { simple_response 200 } }.
|
|
@@ -111,7 +116,7 @@ RSpec.describe HTTP::Redirector do
|
|
|
111
116
|
let(:options) { {:strict => false} }
|
|
112
117
|
|
|
113
118
|
it "it follows with original verb if it's safe" do
|
|
114
|
-
req = HTTP::Request.new :head, "http://example.com"
|
|
119
|
+
req = HTTP::Request.new :verb => :head, :uri => "http://example.com"
|
|
115
120
|
res = redirect_response 300, "http://example.com/1"
|
|
116
121
|
|
|
117
122
|
redirector.perform(req, res) do |prev_req, _|
|
|
@@ -121,7 +126,7 @@ RSpec.describe HTTP::Redirector do
|
|
|
121
126
|
end
|
|
122
127
|
|
|
123
128
|
it "it follows with GET if original request was PUT" do
|
|
124
|
-
req = HTTP::Request.new :put, "http://example.com"
|
|
129
|
+
req = HTTP::Request.new :verb => :put, :uri => "http://example.com"
|
|
125
130
|
res = redirect_response 300, "http://example.com/1"
|
|
126
131
|
|
|
127
132
|
redirector.perform(req, res) do |prev_req, _|
|
|
@@ -131,7 +136,7 @@ RSpec.describe HTTP::Redirector do
|
|
|
131
136
|
end
|
|
132
137
|
|
|
133
138
|
it "it follows with GET if original request was POST" do
|
|
134
|
-
req = HTTP::Request.new :post, "http://example.com"
|
|
139
|
+
req = HTTP::Request.new :verb => :post, :uri => "http://example.com"
|
|
135
140
|
res = redirect_response 300, "http://example.com/1"
|
|
136
141
|
|
|
137
142
|
redirector.perform(req, res) do |prev_req, _|
|
|
@@ -141,7 +146,7 @@ RSpec.describe HTTP::Redirector do
|
|
|
141
146
|
end
|
|
142
147
|
|
|
143
148
|
it "it follows with GET if original request was DELETE" do
|
|
144
|
-
req = HTTP::Request.new :delete, "http://example.com"
|
|
149
|
+
req = HTTP::Request.new :verb => :delete, :uri => "http://example.com"
|
|
145
150
|
res = redirect_response 300, "http://example.com/1"
|
|
146
151
|
|
|
147
152
|
redirector.perform(req, res) do |prev_req, _|
|
|
@@ -157,7 +162,7 @@ RSpec.describe HTTP::Redirector do
|
|
|
157
162
|
let(:options) { {:strict => true} }
|
|
158
163
|
|
|
159
164
|
it "it follows with original verb if it's safe" do
|
|
160
|
-
req = HTTP::Request.new :head, "http://example.com"
|
|
165
|
+
req = HTTP::Request.new :verb => :head, :uri => "http://example.com"
|
|
161
166
|
res = redirect_response 301, "http://example.com/1"
|
|
162
167
|
|
|
163
168
|
redirector.perform(req, res) do |prev_req, _|
|
|
@@ -167,7 +172,7 @@ RSpec.describe HTTP::Redirector do
|
|
|
167
172
|
end
|
|
168
173
|
|
|
169
174
|
it "raises StateError if original request was PUT" do
|
|
170
|
-
req = HTTP::Request.new :put, "http://example.com"
|
|
175
|
+
req = HTTP::Request.new :verb => :put, :uri => "http://example.com"
|
|
171
176
|
res = redirect_response 301, "http://example.com/1"
|
|
172
177
|
|
|
173
178
|
expect { redirector.perform(req, res) { simple_response 200 } }.
|
|
@@ -175,7 +180,7 @@ RSpec.describe HTTP::Redirector do
|
|
|
175
180
|
end
|
|
176
181
|
|
|
177
182
|
it "raises StateError if original request was POST" do
|
|
178
|
-
req = HTTP::Request.new :post, "http://example.com"
|
|
183
|
+
req = HTTP::Request.new :verb => :post, :uri => "http://example.com"
|
|
179
184
|
res = redirect_response 301, "http://example.com/1"
|
|
180
185
|
|
|
181
186
|
expect { redirector.perform(req, res) { simple_response 200 } }.
|
|
@@ -183,7 +188,7 @@ RSpec.describe HTTP::Redirector do
|
|
|
183
188
|
end
|
|
184
189
|
|
|
185
190
|
it "raises StateError if original request was DELETE" do
|
|
186
|
-
req = HTTP::Request.new :delete, "http://example.com"
|
|
191
|
+
req = HTTP::Request.new :verb => :delete, :uri => "http://example.com"
|
|
187
192
|
res = redirect_response 301, "http://example.com/1"
|
|
188
193
|
|
|
189
194
|
expect { redirector.perform(req, res) { simple_response 200 } }.
|
|
@@ -195,7 +200,7 @@ RSpec.describe HTTP::Redirector do
|
|
|
195
200
|
let(:options) { {:strict => false} }
|
|
196
201
|
|
|
197
202
|
it "it follows with original verb if it's safe" do
|
|
198
|
-
req = HTTP::Request.new :head, "http://example.com"
|
|
203
|
+
req = HTTP::Request.new :verb => :head, :uri => "http://example.com"
|
|
199
204
|
res = redirect_response 301, "http://example.com/1"
|
|
200
205
|
|
|
201
206
|
redirector.perform(req, res) do |prev_req, _|
|
|
@@ -205,7 +210,7 @@ RSpec.describe HTTP::Redirector do
|
|
|
205
210
|
end
|
|
206
211
|
|
|
207
212
|
it "it follows with GET if original request was PUT" do
|
|
208
|
-
req = HTTP::Request.new :put, "http://example.com"
|
|
213
|
+
req = HTTP::Request.new :verb => :put, :uri => "http://example.com"
|
|
209
214
|
res = redirect_response 301, "http://example.com/1"
|
|
210
215
|
|
|
211
216
|
redirector.perform(req, res) do |prev_req, _|
|
|
@@ -215,7 +220,7 @@ RSpec.describe HTTP::Redirector do
|
|
|
215
220
|
end
|
|
216
221
|
|
|
217
222
|
it "it follows with GET if original request was POST" do
|
|
218
|
-
req = HTTP::Request.new :post, "http://example.com"
|
|
223
|
+
req = HTTP::Request.new :verb => :post, :uri => "http://example.com"
|
|
219
224
|
res = redirect_response 301, "http://example.com/1"
|
|
220
225
|
|
|
221
226
|
redirector.perform(req, res) do |prev_req, _|
|
|
@@ -225,7 +230,7 @@ RSpec.describe HTTP::Redirector do
|
|
|
225
230
|
end
|
|
226
231
|
|
|
227
232
|
it "it follows with GET if original request was DELETE" do
|
|
228
|
-
req = HTTP::Request.new :delete, "http://example.com"
|
|
233
|
+
req = HTTP::Request.new :verb => :delete, :uri => "http://example.com"
|
|
229
234
|
res = redirect_response 301, "http://example.com/1"
|
|
230
235
|
|
|
231
236
|
redirector.perform(req, res) do |prev_req, _|
|
|
@@ -241,7 +246,7 @@ RSpec.describe HTTP::Redirector do
|
|
|
241
246
|
let(:options) { {:strict => true} }
|
|
242
247
|
|
|
243
248
|
it "it follows with original verb if it's safe" do
|
|
244
|
-
req = HTTP::Request.new :head, "http://example.com"
|
|
249
|
+
req = HTTP::Request.new :verb => :head, :uri => "http://example.com"
|
|
245
250
|
res = redirect_response 302, "http://example.com/1"
|
|
246
251
|
|
|
247
252
|
redirector.perform(req, res) do |prev_req, _|
|
|
@@ -251,7 +256,7 @@ RSpec.describe HTTP::Redirector do
|
|
|
251
256
|
end
|
|
252
257
|
|
|
253
258
|
it "raises StateError if original request was PUT" do
|
|
254
|
-
req = HTTP::Request.new :put, "http://example.com"
|
|
259
|
+
req = HTTP::Request.new :verb => :put, :uri => "http://example.com"
|
|
255
260
|
res = redirect_response 302, "http://example.com/1"
|
|
256
261
|
|
|
257
262
|
expect { redirector.perform(req, res) { simple_response 200 } }.
|
|
@@ -259,7 +264,7 @@ RSpec.describe HTTP::Redirector do
|
|
|
259
264
|
end
|
|
260
265
|
|
|
261
266
|
it "raises StateError if original request was POST" do
|
|
262
|
-
req = HTTP::Request.new :post, "http://example.com"
|
|
267
|
+
req = HTTP::Request.new :verb => :post, :uri => "http://example.com"
|
|
263
268
|
res = redirect_response 302, "http://example.com/1"
|
|
264
269
|
|
|
265
270
|
expect { redirector.perform(req, res) { simple_response 200 } }.
|
|
@@ -267,7 +272,7 @@ RSpec.describe HTTP::Redirector do
|
|
|
267
272
|
end
|
|
268
273
|
|
|
269
274
|
it "raises StateError if original request was DELETE" do
|
|
270
|
-
req = HTTP::Request.new :delete, "http://example.com"
|
|
275
|
+
req = HTTP::Request.new :verb => :delete, :uri => "http://example.com"
|
|
271
276
|
res = redirect_response 302, "http://example.com/1"
|
|
272
277
|
|
|
273
278
|
expect { redirector.perform(req, res) { simple_response 200 } }.
|
|
@@ -279,7 +284,7 @@ RSpec.describe HTTP::Redirector do
|
|
|
279
284
|
let(:options) { {:strict => false} }
|
|
280
285
|
|
|
281
286
|
it "it follows with original verb if it's safe" do
|
|
282
|
-
req = HTTP::Request.new :head, "http://example.com"
|
|
287
|
+
req = HTTP::Request.new :verb => :head, :uri => "http://example.com"
|
|
283
288
|
res = redirect_response 302, "http://example.com/1"
|
|
284
289
|
|
|
285
290
|
redirector.perform(req, res) do |prev_req, _|
|
|
@@ -289,7 +294,7 @@ RSpec.describe HTTP::Redirector do
|
|
|
289
294
|
end
|
|
290
295
|
|
|
291
296
|
it "it follows with GET if original request was PUT" do
|
|
292
|
-
req = HTTP::Request.new :put, "http://example.com"
|
|
297
|
+
req = HTTP::Request.new :verb => :put, :uri => "http://example.com"
|
|
293
298
|
res = redirect_response 302, "http://example.com/1"
|
|
294
299
|
|
|
295
300
|
redirector.perform(req, res) do |prev_req, _|
|
|
@@ -299,7 +304,7 @@ RSpec.describe HTTP::Redirector do
|
|
|
299
304
|
end
|
|
300
305
|
|
|
301
306
|
it "it follows with GET if original request was POST" do
|
|
302
|
-
req = HTTP::Request.new :post, "http://example.com"
|
|
307
|
+
req = HTTP::Request.new :verb => :post, :uri => "http://example.com"
|
|
303
308
|
res = redirect_response 302, "http://example.com/1"
|
|
304
309
|
|
|
305
310
|
redirector.perform(req, res) do |prev_req, _|
|
|
@@ -309,7 +314,7 @@ RSpec.describe HTTP::Redirector do
|
|
|
309
314
|
end
|
|
310
315
|
|
|
311
316
|
it "it follows with GET if original request was DELETE" do
|
|
312
|
-
req = HTTP::Request.new :delete, "http://example.com"
|
|
317
|
+
req = HTTP::Request.new :verb => :delete, :uri => "http://example.com"
|
|
313
318
|
res = redirect_response 302, "http://example.com/1"
|
|
314
319
|
|
|
315
320
|
redirector.perform(req, res) do |prev_req, _|
|
|
@@ -322,7 +327,7 @@ RSpec.describe HTTP::Redirector do
|
|
|
322
327
|
|
|
323
328
|
context "following 303 redirect" do
|
|
324
329
|
it "follows with HEAD if original request was HEAD" do
|
|
325
|
-
req = HTTP::Request.new :head, "http://example.com"
|
|
330
|
+
req = HTTP::Request.new :verb => :head, :uri => "http://example.com"
|
|
326
331
|
res = redirect_response 303, "http://example.com/1"
|
|
327
332
|
|
|
328
333
|
redirector.perform(req, res) do |prev_req, _|
|
|
@@ -332,7 +337,7 @@ RSpec.describe HTTP::Redirector do
|
|
|
332
337
|
end
|
|
333
338
|
|
|
334
339
|
it "follows with GET if original request was GET" do
|
|
335
|
-
req = HTTP::Request.new :get, "http://example.com"
|
|
340
|
+
req = HTTP::Request.new :verb => :get, :uri => "http://example.com"
|
|
336
341
|
res = redirect_response 303, "http://example.com/1"
|
|
337
342
|
|
|
338
343
|
redirector.perform(req, res) do |prev_req, _|
|
|
@@ -342,7 +347,7 @@ RSpec.describe HTTP::Redirector do
|
|
|
342
347
|
end
|
|
343
348
|
|
|
344
349
|
it "follows with GET if original request was neither GET nor HEAD" do
|
|
345
|
-
req = HTTP::Request.new :post, "http://example.com"
|
|
350
|
+
req = HTTP::Request.new :verb => :post, :uri => "http://example.com"
|
|
346
351
|
res = redirect_response 303, "http://example.com/1"
|
|
347
352
|
|
|
348
353
|
redirector.perform(req, res) do |prev_req, _|
|
|
@@ -354,7 +359,7 @@ RSpec.describe HTTP::Redirector do
|
|
|
354
359
|
|
|
355
360
|
context "following 307 redirect" do
|
|
356
361
|
it "follows with original request's verb" do
|
|
357
|
-
req = HTTP::Request.new :post, "http://example.com"
|
|
362
|
+
req = HTTP::Request.new :verb => :post, :uri => "http://example.com"
|
|
358
363
|
res = redirect_response 307, "http://example.com/1"
|
|
359
364
|
|
|
360
365
|
redirector.perform(req, res) do |prev_req, _|
|
|
@@ -366,7 +371,7 @@ RSpec.describe HTTP::Redirector do
|
|
|
366
371
|
|
|
367
372
|
context "following 308 redirect" do
|
|
368
373
|
it "follows with original request's verb" do
|
|
369
|
-
req = HTTP::Request.new :post, "http://example.com"
|
|
374
|
+
req = HTTP::Request.new :verb => :post, :uri => "http://example.com"
|
|
370
375
|
res = redirect_response 308, "http://example.com/1"
|
|
371
376
|
|
|
372
377
|
redirector.perform(req, res) do |prev_req, _|
|
|
@@ -37,7 +37,7 @@ RSpec.describe HTTP::Request::Writer do
|
|
|
37
37
|
let(:body) { 123 }
|
|
38
38
|
|
|
39
39
|
it "raises an error" do
|
|
40
|
-
expect { writer }.to raise_error
|
|
40
|
+
expect { writer }.to raise_error(HTTP::RequestError)
|
|
41
41
|
end
|
|
42
42
|
end
|
|
43
43
|
end
|
|
@@ -59,12 +59,12 @@ RSpec.describe HTTP::Request::Writer do
|
|
|
59
59
|
|
|
60
60
|
context "when Transfer-Encoding not set" do
|
|
61
61
|
let(:headers) { HTTP::Headers.new }
|
|
62
|
-
specify { expect { writer.stream }.to raise_error }
|
|
62
|
+
specify { expect { writer.stream }.to raise_error(HTTP::RequestError) }
|
|
63
63
|
end
|
|
64
64
|
|
|
65
65
|
context "when Transfer-Encoding is not chunked" do
|
|
66
66
|
let(:headers) { HTTP::Headers.coerce "Transfer-Encoding" => "gzip" }
|
|
67
|
-
specify { expect { writer.stream }.to raise_error }
|
|
67
|
+
specify { expect { writer.stream }.to raise_error(HTTP::RequestError) }
|
|
68
68
|
end
|
|
69
69
|
end
|
|
70
70
|
|
|
@@ -5,14 +5,21 @@ RSpec.describe HTTP::Request do
|
|
|
5
5
|
let(:headers) { {:accept => "text/html"} }
|
|
6
6
|
let(:request_uri) { "http://example.com/foo?bar=baz" }
|
|
7
7
|
|
|
8
|
-
subject
|
|
8
|
+
subject :request do
|
|
9
|
+
HTTP::Request.new(
|
|
10
|
+
:verb => :get,
|
|
11
|
+
:uri => request_uri,
|
|
12
|
+
:headers => headers,
|
|
13
|
+
:proxy => proxy
|
|
14
|
+
)
|
|
15
|
+
end
|
|
9
16
|
|
|
10
17
|
it "includes HTTP::Headers::Mixin" do
|
|
11
18
|
expect(described_class).to include HTTP::Headers::Mixin
|
|
12
19
|
end
|
|
13
20
|
|
|
14
21
|
it "requires URI to have scheme part" do
|
|
15
|
-
expect { HTTP::Request.new(:get, "example.com/") }.to \
|
|
22
|
+
expect { HTTP::Request.new(:verb => :get, :uri => "example.com/") }.to \
|
|
16
23
|
raise_error(HTTP::Request::UnsupportedSchemeError)
|
|
17
24
|
end
|
|
18
25
|
|
|
@@ -63,7 +70,16 @@ RSpec.describe HTTP::Request do
|
|
|
63
70
|
let(:headers) { {:accept => "text/html"} }
|
|
64
71
|
let(:proxy) { {:proxy_username => "douglas", :proxy_password => "adams"} }
|
|
65
72
|
let(:body) { "The Ultimate Question" }
|
|
66
|
-
|
|
73
|
+
|
|
74
|
+
let :request do
|
|
75
|
+
HTTP::Request.new(
|
|
76
|
+
:verb => :post,
|
|
77
|
+
:uri => "http://example.com/",
|
|
78
|
+
:headers => headers,
|
|
79
|
+
:proxy => proxy,
|
|
80
|
+
:body => body
|
|
81
|
+
)
|
|
82
|
+
end
|
|
67
83
|
|
|
68
84
|
subject(:redirected) { request.redirect "http://blog.example.com/" }
|
|
69
85
|
|
|
@@ -105,8 +121,17 @@ RSpec.describe HTTP::Request do
|
|
|
105
121
|
end
|
|
106
122
|
|
|
107
123
|
context "with original URI having non-standard port" do
|
|
108
|
-
let
|
|
109
|
-
|
|
124
|
+
let :request do
|
|
125
|
+
HTTP::Request.new(
|
|
126
|
+
:verb => :post,
|
|
127
|
+
:uri => "http://example.com:8080/",
|
|
128
|
+
:headers => headers,
|
|
129
|
+
:proxy => proxy,
|
|
130
|
+
:body => body
|
|
131
|
+
)
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
its(:uri) { is_expected.to eq HTTP::URI.parse "http://example.com:8080/blog" }
|
|
110
135
|
end
|
|
111
136
|
end
|
|
112
137
|
|
|
@@ -124,8 +149,17 @@ RSpec.describe HTTP::Request do
|
|
|
124
149
|
end
|
|
125
150
|
|
|
126
151
|
context "with original URI having non-standard port" do
|
|
127
|
-
let
|
|
128
|
-
|
|
152
|
+
let :request do
|
|
153
|
+
HTTP::Request.new(
|
|
154
|
+
:verb => :post,
|
|
155
|
+
:uri => "http://example.com:8080/",
|
|
156
|
+
:headers => headers,
|
|
157
|
+
:proxy => proxy,
|
|
158
|
+
:body => body
|
|
159
|
+
)
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
its(:uri) { is_expected.to eq HTTP::URI.parse "http://example.com:8080/blog" }
|
|
129
163
|
end
|
|
130
164
|
end
|
|
131
165
|
|
|
@@ -4,7 +4,7 @@ RSpec.describe HTTP::Response::Body do
|
|
|
4
4
|
|
|
5
5
|
before { allow(client).to receive(:readpartial) { chunks.shift } }
|
|
6
6
|
|
|
7
|
-
subject(:body) { described_class.new client }
|
|
7
|
+
subject(:body) { described_class.new client, Encoding::UTF_8 }
|
|
8
8
|
|
|
9
9
|
it "streams bodies from responses" do
|
|
10
10
|
expect(subject.to_s).to eq "Hello, World!"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
RSpec.describe HTTP::Response::Status do
|
|
2
2
|
describe ".new" do
|
|
3
3
|
it "fails if given value does not respond to #to_i" do
|
|
4
|
-
expect { described_class.new double }.to raise_error
|
|
4
|
+
expect { described_class.new double }.to raise_error TypeError
|
|
5
5
|
end
|
|
6
6
|
|
|
7
7
|
it "accepts any object that responds to #to_i" do
|
|
@@ -34,8 +34,8 @@ RSpec.describe HTTP::Response::Status do
|
|
|
34
34
|
end
|
|
35
35
|
end
|
|
36
36
|
|
|
37
|
-
describe "#
|
|
38
|
-
subject { described_class.new(code).
|
|
37
|
+
describe "#to_sym" do
|
|
38
|
+
subject { described_class.new(code).to_sym }
|
|
39
39
|
|
|
40
40
|
context "with unknown code" do
|
|
41
41
|
let(:code) { 1024 }
|
|
@@ -2,7 +2,16 @@ RSpec.describe HTTP::Response do
|
|
|
2
2
|
let(:body) { "Hello world!" }
|
|
3
3
|
let(:uri) { "http://example.com/" }
|
|
4
4
|
let(:headers) { {} }
|
|
5
|
-
|
|
5
|
+
|
|
6
|
+
subject(:response) do
|
|
7
|
+
HTTP::Response.new(
|
|
8
|
+
:status => 200,
|
|
9
|
+
:version => "1.1",
|
|
10
|
+
:headers => headers,
|
|
11
|
+
:body => body,
|
|
12
|
+
:uri => uri
|
|
13
|
+
)
|
|
14
|
+
end
|
|
6
15
|
|
|
7
16
|
it "includes HTTP::Headers::Mixin" do
|
|
8
17
|
expect(described_class).to include HTTP::Headers::Mixin
|
data/spec/lib/http_spec.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
|
|
1
3
|
require "json"
|
|
2
4
|
|
|
3
5
|
require "support/dummy_server"
|
|
@@ -160,14 +162,36 @@ RSpec.describe HTTP do
|
|
|
160
162
|
context "loading binary data" do
|
|
161
163
|
it "is encoded as bytes" do
|
|
162
164
|
response = HTTP.get "#{dummy.endpoint}/bytes"
|
|
163
|
-
expect(response.to_s.encoding).to eq(Encoding::
|
|
165
|
+
expect(response.to_s.encoding).to eq(Encoding::BINARY)
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
context "loading endpoint with charset" do
|
|
170
|
+
it "uses charset from headers" do
|
|
171
|
+
response = HTTP.get "#{dummy.endpoint}/iso-8859-1"
|
|
172
|
+
expect(response.to_s.encoding).to eq(Encoding::ISO8859_1)
|
|
173
|
+
expect(response.to_s.encode(Encoding::UTF_8)).to eq("testæ")
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
context "with encoding option" do
|
|
177
|
+
it "respects option" do
|
|
178
|
+
response = HTTP.get "#{dummy.endpoint}/iso-8859-1", "encoding" => Encoding::BINARY
|
|
179
|
+
expect(response.to_s.encoding).to eq(Encoding::BINARY)
|
|
180
|
+
end
|
|
164
181
|
end
|
|
165
182
|
end
|
|
166
183
|
|
|
167
|
-
context "
|
|
168
|
-
it "
|
|
184
|
+
context "passing a string encoding type" do
|
|
185
|
+
it "finds encoding" do
|
|
186
|
+
response = HTTP.get dummy.endpoint, "encoding" => "ascii"
|
|
187
|
+
expect(response.to_s.encoding).to eq(Encoding::ASCII)
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
context "loading text with no charset" do
|
|
192
|
+
it "is binary encoded" do
|
|
169
193
|
response = HTTP.get dummy.endpoint
|
|
170
|
-
expect(response.to_s.encoding).to eq(Encoding::
|
|
194
|
+
expect(response.to_s.encoding).to eq(Encoding::BINARY)
|
|
171
195
|
end
|
|
172
196
|
end
|
|
173
197
|
|
|
@@ -201,12 +225,12 @@ RSpec.describe HTTP do
|
|
|
201
225
|
describe ".auth" do
|
|
202
226
|
it "sets Authorization header to the given value" do
|
|
203
227
|
client = HTTP.auth "abc"
|
|
204
|
-
expect(client.
|
|
228
|
+
expect(client.default_options.headers[:authorization]).to eq "abc"
|
|
205
229
|
end
|
|
206
230
|
|
|
207
231
|
it "accepts any #to_s object" do
|
|
208
232
|
client = HTTP.auth double :to_s => "abc"
|
|
209
|
-
expect(client.
|
|
233
|
+
expect(client.default_options.headers[:authorization]).to eq "abc"
|
|
210
234
|
end
|
|
211
235
|
end
|
|
212
236
|
|
|
@@ -225,7 +249,7 @@ RSpec.describe HTTP do
|
|
|
225
249
|
|
|
226
250
|
it "sets Authorization header with proper BasicAuth value" do
|
|
227
251
|
client = HTTP.basic_auth :user => "foo", :pass => "bar"
|
|
228
|
-
expect(client.
|
|
252
|
+
expect(client.default_options.headers[:authorization]).
|
|
229
253
|
to match(%r{^Basic [A-Za-z0-9+/]+=*$})
|
|
230
254
|
end
|
|
231
255
|
end
|
|
@@ -337,5 +361,40 @@ RSpec.describe HTTP do
|
|
|
337
361
|
client = HTTP.headers("Cookie" => "foo=bar").cookies(:baz => :moo)
|
|
338
362
|
expect(client.get(endpoint).to_s).to eq "foo: bar\nbaz: moo"
|
|
339
363
|
end
|
|
364
|
+
|
|
365
|
+
it "unifies socket errors into HTTP::ConnectionError" do
|
|
366
|
+
expect { HTTP.get "http://thishostshouldnotexists.com" }.to raise_error HTTP::ConnectionError
|
|
367
|
+
expect { HTTP.get "http://127.0.0.1:000" }.to raise_error HTTP::ConnectionError
|
|
368
|
+
end
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
describe ".nodelay" do
|
|
372
|
+
before do
|
|
373
|
+
HTTP.default_options = {:socket_class => socket_spy_class}
|
|
374
|
+
end
|
|
375
|
+
|
|
376
|
+
after do
|
|
377
|
+
HTTP.default_options = {}
|
|
378
|
+
end
|
|
379
|
+
|
|
380
|
+
let(:socket_spy_class) do
|
|
381
|
+
Class.new(TCPSocket) do
|
|
382
|
+
def self.setsockopt_calls
|
|
383
|
+
@setsockopt_calls ||= []
|
|
384
|
+
end
|
|
385
|
+
|
|
386
|
+
def setsockopt(*args)
|
|
387
|
+
self.class.setsockopt_calls << args
|
|
388
|
+
super
|
|
389
|
+
end
|
|
390
|
+
end
|
|
391
|
+
end
|
|
392
|
+
|
|
393
|
+
it "sets TCP_NODELAY on the underlying socket" do
|
|
394
|
+
HTTP.get(dummy.endpoint)
|
|
395
|
+
expect(socket_spy_class.setsockopt_calls).to eq([])
|
|
396
|
+
HTTP.nodelay.get(dummy.endpoint)
|
|
397
|
+
expect(socket_spy_class.setsockopt_calls).to eq([[Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1]])
|
|
398
|
+
end
|
|
340
399
|
end
|
|
341
400
|
end
|
data/spec/spec_helper.rb
CHANGED
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
require "simplecov"
|
|
4
4
|
require "coveralls"
|
|
5
5
|
|
|
6
|
-
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
|
|
6
|
+
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new([
|
|
7
7
|
SimpleCov::Formatter::HTMLFormatter,
|
|
8
8
|
Coveralls::SimpleCov::Formatter
|
|
9
|
-
]
|
|
9
|
+
])
|
|
10
10
|
|
|
11
11
|
SimpleCov.start do
|
|
12
12
|
add_filter "/spec/"
|
|
@@ -56,7 +56,7 @@ RSpec.shared_context "handles shared connections" do
|
|
|
56
56
|
# rubocop:enable Style/RescueModifier
|
|
57
57
|
|
|
58
58
|
# Should error because we tried to use a bad socket
|
|
59
|
-
expect { client.get("#{server.endpoint}/socket").body.to_s }.to raise_error
|
|
59
|
+
expect { client.get("#{server.endpoint}/socket").body.to_s }.to raise_error HTTP::ConnectionError
|
|
60
60
|
|
|
61
61
|
# Should succeed since we create a new socket
|
|
62
62
|
second_socket = client.get("#{server.endpoint}/socket").body.to_s
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
|
|
1
3
|
class DummyServer < WEBrick::HTTPServer
|
|
2
4
|
class Servlet < WEBrick::HTTPServlet::AbstractServlet
|
|
3
5
|
def self.sockets
|
|
@@ -129,6 +131,11 @@ class DummyServer < WEBrick::HTTPServer
|
|
|
129
131
|
res.body = bytes.pack("c*")
|
|
130
132
|
end
|
|
131
133
|
|
|
134
|
+
get "/iso-8859-1" do |_req, res|
|
|
135
|
+
res["Content-Type"] = "text/plain; charset=ISO-8859-1"
|
|
136
|
+
res.body = "testæ".encode(Encoding::ISO8859_1)
|
|
137
|
+
end
|
|
138
|
+
|
|
132
139
|
get "/cookies" do |req, res|
|
|
133
140
|
res["Set-Cookie"] = "foo=bar"
|
|
134
141
|
res.body = req.cookies.map { |c| [c.name, c.value].join ": " }.join("\n")
|
|
@@ -59,6 +59,9 @@ RSpec.shared_context "HTTP handling" do
|
|
|
59
59
|
let(:read_timeout) { 2.5 }
|
|
60
60
|
|
|
61
61
|
it "does not time out" do
|
|
62
|
+
# TODO: investigate sporadic JRuby timeouts on CI
|
|
63
|
+
skip "flaky environment" if flaky_env?
|
|
64
|
+
|
|
62
65
|
expect { client.get("#{server.endpoint}/sleep").body.to_s }.to_not raise_error
|
|
63
66
|
end
|
|
64
67
|
end
|
|
@@ -93,6 +96,9 @@ RSpec.shared_context "HTTP handling" do
|
|
|
93
96
|
let(:read_timeout) { 2.5 }
|
|
94
97
|
|
|
95
98
|
it "does not timeout" do
|
|
99
|
+
# TODO: investigate sporadic JRuby timeouts on CI
|
|
100
|
+
skip "flaky environment" if flaky_env?
|
|
101
|
+
|
|
96
102
|
client.get("#{server.endpoint}/sleep").body.to_s
|
|
97
103
|
client.get("#{server.endpoint}/sleep").body.to_s
|
|
98
104
|
end
|
|
@@ -170,7 +176,7 @@ RSpec.shared_context "HTTP handling" do
|
|
|
170
176
|
# rubocop:enable Style/RescueModifier
|
|
171
177
|
|
|
172
178
|
# Should error because we tried to use a bad socket
|
|
173
|
-
expect { client.get("#{server.endpoint}/socket").body.to_s }.to raise_error
|
|
179
|
+
expect { client.get("#{server.endpoint}/socket").body.to_s }.to raise_error HTTP::ConnectionError
|
|
174
180
|
|
|
175
181
|
# Should succeed since we create a new socket
|
|
176
182
|
second_socket_id = client.get("#{server.endpoint}/socket").body.to_s
|
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.
|
|
4
|
+
version: 1.0.0
|
|
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-
|
|
14
|
+
date: 2015-12-25 00:00:00.000000000 Z
|
|
15
15
|
dependencies:
|
|
16
16
|
- !ruby/object:Gem::Dependency
|
|
17
17
|
name: http_parser.rb
|
|
@@ -104,7 +104,6 @@ files:
|
|
|
104
104
|
- LICENSE.txt
|
|
105
105
|
- README.md
|
|
106
106
|
- Rakefile
|
|
107
|
-
- examples/parallel_requests_with_celluloid.rb
|
|
108
107
|
- http.gemspec
|
|
109
108
|
- lib/http.rb
|
|
110
109
|
- lib/http/chainable.rb
|
|
@@ -184,7 +183,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
184
183
|
version: '0'
|
|
185
184
|
requirements: []
|
|
186
185
|
rubyforge_project:
|
|
187
|
-
rubygems_version: 2.4.
|
|
186
|
+
rubygems_version: 2.4.8
|
|
188
187
|
signing_key:
|
|
189
188
|
specification_version: 4
|
|
190
189
|
summary: HTTP should be easy
|