http 5.2.0 → 6.0.2

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.
Files changed (128) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +110 -13
  4. data/http.gemspec +38 -35
  5. data/lib/http/base64.rb +22 -0
  6. data/lib/http/chainable/helpers.rb +62 -0
  7. data/lib/http/chainable/verbs.rb +136 -0
  8. data/lib/http/chainable.rb +249 -129
  9. data/lib/http/client.rb +158 -127
  10. data/lib/http/connection/internals.rb +141 -0
  11. data/lib/http/connection.rb +128 -97
  12. data/lib/http/content_type.rb +61 -6
  13. data/lib/http/errors.rb +41 -1
  14. data/lib/http/feature.rb +67 -6
  15. data/lib/http/features/auto_deflate.rb +124 -17
  16. data/lib/http/features/auto_inflate.rb +38 -15
  17. data/lib/http/features/caching/entry.rb +178 -0
  18. data/lib/http/features/caching/in_memory_store.rb +63 -0
  19. data/lib/http/features/caching.rb +216 -0
  20. data/lib/http/features/digest_auth.rb +234 -0
  21. data/lib/http/features/instrumentation.rb +97 -17
  22. data/lib/http/features/logging.rb +183 -5
  23. data/lib/http/features/normalize_uri.rb +17 -0
  24. data/lib/http/features/raise_error.rb +37 -0
  25. data/lib/http/form_data/composite_io.rb +106 -0
  26. data/lib/http/form_data/file.rb +95 -0
  27. data/lib/http/form_data/multipart/param.rb +62 -0
  28. data/lib/http/form_data/multipart.rb +106 -0
  29. data/lib/http/form_data/part.rb +52 -0
  30. data/lib/http/form_data/readable.rb +58 -0
  31. data/lib/http/form_data/urlencoded.rb +175 -0
  32. data/lib/http/form_data/version.rb +8 -0
  33. data/lib/http/form_data.rb +102 -0
  34. data/lib/http/headers/known.rb +3 -0
  35. data/lib/http/headers/normalizer.rb +50 -0
  36. data/lib/http/headers.rb +185 -92
  37. data/lib/http/mime_type/adapter.rb +24 -9
  38. data/lib/http/mime_type/json.rb +19 -4
  39. data/lib/http/mime_type.rb +21 -3
  40. data/lib/http/options/definitions.rb +189 -0
  41. data/lib/http/options.rb +172 -125
  42. data/lib/http/redirector.rb +80 -75
  43. data/lib/http/request/body.rb +87 -6
  44. data/lib/http/request/builder.rb +184 -0
  45. data/lib/http/request/proxy.rb +83 -0
  46. data/lib/http/request/writer.rb +78 -17
  47. data/lib/http/request.rb +216 -99
  48. data/lib/http/response/body.rb +103 -18
  49. data/lib/http/response/inflater.rb +35 -7
  50. data/lib/http/response/parser.rb +98 -4
  51. data/lib/http/response/status/reasons.rb +2 -4
  52. data/lib/http/response/status.rb +141 -31
  53. data/lib/http/response.rb +219 -61
  54. data/lib/http/retriable/delay_calculator.rb +91 -0
  55. data/lib/http/retriable/errors.rb +35 -0
  56. data/lib/http/retriable/performer.rb +197 -0
  57. data/lib/http/session.rb +280 -0
  58. data/lib/http/timeout/global.rb +147 -34
  59. data/lib/http/timeout/null.rb +155 -9
  60. data/lib/http/timeout/per_operation.rb +139 -18
  61. data/lib/http/uri/normalizer.rb +82 -0
  62. data/lib/http/uri/parsing.rb +182 -0
  63. data/lib/http/uri.rb +289 -124
  64. data/lib/http/version.rb +2 -1
  65. data/lib/http.rb +11 -1
  66. data/sig/http.rbs +1619 -0
  67. metadata +42 -175
  68. data/.github/workflows/ci.yml +0 -67
  69. data/.gitignore +0 -15
  70. data/.rspec +0 -1
  71. data/.rubocop/layout.yml +0 -8
  72. data/.rubocop/metrics.yml +0 -4
  73. data/.rubocop/style.yml +0 -32
  74. data/.rubocop.yml +0 -11
  75. data/.rubocop_todo.yml +0 -206
  76. data/.yardopts +0 -2
  77. data/CHANGELOG.md +0 -41
  78. data/CHANGES_OLD.md +0 -1002
  79. data/CONTRIBUTING.md +0 -26
  80. data/Gemfile +0 -50
  81. data/Guardfile +0 -18
  82. data/Rakefile +0 -64
  83. data/SECURITY.md +0 -17
  84. data/lib/http/headers/mixin.rb +0 -34
  85. data/logo.png +0 -0
  86. data/spec/lib/http/client_spec.rb +0 -556
  87. data/spec/lib/http/connection_spec.rb +0 -88
  88. data/spec/lib/http/content_type_spec.rb +0 -47
  89. data/spec/lib/http/features/auto_deflate_spec.rb +0 -77
  90. data/spec/lib/http/features/auto_inflate_spec.rb +0 -86
  91. data/spec/lib/http/features/instrumentation_spec.rb +0 -81
  92. data/spec/lib/http/features/logging_spec.rb +0 -65
  93. data/spec/lib/http/headers/mixin_spec.rb +0 -36
  94. data/spec/lib/http/headers_spec.rb +0 -527
  95. data/spec/lib/http/options/body_spec.rb +0 -15
  96. data/spec/lib/http/options/features_spec.rb +0 -33
  97. data/spec/lib/http/options/form_spec.rb +0 -15
  98. data/spec/lib/http/options/headers_spec.rb +0 -24
  99. data/spec/lib/http/options/json_spec.rb +0 -15
  100. data/spec/lib/http/options/merge_spec.rb +0 -68
  101. data/spec/lib/http/options/new_spec.rb +0 -30
  102. data/spec/lib/http/options/proxy_spec.rb +0 -20
  103. data/spec/lib/http/options_spec.rb +0 -13
  104. data/spec/lib/http/redirector_spec.rb +0 -529
  105. data/spec/lib/http/request/body_spec.rb +0 -211
  106. data/spec/lib/http/request/writer_spec.rb +0 -121
  107. data/spec/lib/http/request_spec.rb +0 -234
  108. data/spec/lib/http/response/body_spec.rb +0 -85
  109. data/spec/lib/http/response/parser_spec.rb +0 -74
  110. data/spec/lib/http/response/status_spec.rb +0 -253
  111. data/spec/lib/http/response_spec.rb +0 -262
  112. data/spec/lib/http/uri/normalizer_spec.rb +0 -95
  113. data/spec/lib/http/uri_spec.rb +0 -71
  114. data/spec/lib/http_spec.rb +0 -506
  115. data/spec/regression_specs.rb +0 -24
  116. data/spec/spec_helper.rb +0 -88
  117. data/spec/support/black_hole.rb +0 -13
  118. data/spec/support/capture_warning.rb +0 -10
  119. data/spec/support/dummy_server/servlet.rb +0 -190
  120. data/spec/support/dummy_server.rb +0 -43
  121. data/spec/support/fakeio.rb +0 -21
  122. data/spec/support/fuubar.rb +0 -21
  123. data/spec/support/http_handling_shared.rb +0 -190
  124. data/spec/support/proxy_server.rb +0 -39
  125. data/spec/support/servers/config.rb +0 -11
  126. data/spec/support/servers/runner.rb +0 -19
  127. data/spec/support/simplecov.rb +0 -19
  128. data/spec/support/ssl_helper.rb +0 -104
@@ -1,30 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe HTTP::Options, "new" do
4
- it "supports a Options instance" do
5
- opts = HTTP::Options.new
6
- expect(HTTP::Options.new(opts)).to eq(opts)
7
- end
8
-
9
- context "with a Hash" do
10
- it "coerces :response correctly" do
11
- opts = HTTP::Options.new(:response => :object)
12
- expect(opts.response).to eq(:object)
13
- end
14
-
15
- it "coerces :headers correctly" do
16
- opts = HTTP::Options.new(:headers => {:accept => "json"})
17
- expect(opts.headers).to eq([%w[Accept json]])
18
- end
19
-
20
- it "coerces :proxy correctly" do
21
- opts = HTTP::Options.new(:proxy => {:proxy_address => "127.0.0.1", :proxy_port => 8080})
22
- expect(opts.proxy).to eq(:proxy_address => "127.0.0.1", :proxy_port => 8080)
23
- end
24
-
25
- it "coerces :form correctly" do
26
- opts = HTTP::Options.new(:form => {:foo => 42})
27
- expect(opts.form).to eq(:foo => 42)
28
- end
29
- end
30
- end
@@ -1,20 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe HTTP::Options, "proxy" do
4
- let(:opts) { HTTP::Options.new }
5
-
6
- it "defaults to {}" do
7
- expect(opts.proxy).to eq({})
8
- end
9
-
10
- it "may be specified with with_proxy" do
11
- opts2 = opts.with_proxy(:proxy_address => "127.0.0.1", :proxy_port => 8080)
12
- expect(opts.proxy).to eq({})
13
- expect(opts2.proxy).to eq(:proxy_address => "127.0.0.1", :proxy_port => 8080)
14
- end
15
-
16
- it "accepts proxy address, port, username, and password" do
17
- opts2 = opts.with_proxy(:proxy_address => "127.0.0.1", :proxy_port => 8080, :proxy_username => "username", :proxy_password => "password")
18
- expect(opts2.proxy).to eq(:proxy_address => "127.0.0.1", :proxy_port => 8080, :proxy_username => "username", :proxy_password => "password")
19
- end
20
- end
@@ -1,13 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe HTTP::Options do
4
- subject { described_class.new(:response => :body) }
5
-
6
- it "has reader methods for attributes" do
7
- expect(subject.response).to eq(:body)
8
- end
9
-
10
- it "coerces to a Hash" do
11
- expect(subject.to_hash).to be_a(Hash)
12
- end
13
- end
@@ -1,529 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe HTTP::Redirector do
4
- def simple_response(status, body = "", headers = {})
5
- HTTP::Response.new(
6
- :status => status,
7
- :version => "1.1",
8
- :headers => headers,
9
- :body => body,
10
- :request => HTTP::Request.new(:verb => :get, :uri => "http://example.com")
11
- )
12
- end
13
-
14
- def redirect_response(status, location, set_cookie = {})
15
- res = simple_response status, "", "Location" => location
16
- set_cookie.each do |name, value|
17
- res.headers.add("Set-Cookie", "#{name}=#{value}; path=/; httponly; secure; SameSite=none; Secure")
18
- end
19
- res
20
- end
21
-
22
- describe "#strict" do
23
- subject { redirector.strict }
24
-
25
- context "by default" do
26
- let(:redirector) { described_class.new }
27
- it { is_expected.to be true }
28
- end
29
- end
30
-
31
- describe "#max_hops" do
32
- subject { redirector.max_hops }
33
-
34
- context "by default" do
35
- let(:redirector) { described_class.new }
36
- it { is_expected.to eq 5 }
37
- end
38
- end
39
-
40
- describe "#perform" do
41
- let(:options) { {} }
42
- let(:redirector) { described_class.new options }
43
-
44
- it "fails with TooManyRedirectsError if max hops reached" do
45
- req = HTTP::Request.new :verb => :head, :uri => "http://example.com"
46
- res = proc { |prev_req| redirect_response(301, "#{prev_req.uri}/1") }
47
-
48
- expect { redirector.perform(req, res.call(req), &res) }.
49
- to raise_error HTTP::Redirector::TooManyRedirectsError
50
- end
51
-
52
- it "fails with EndlessRedirectError if endless loop detected" do
53
- req = HTTP::Request.new :verb => :head, :uri => "http://example.com"
54
- res = redirect_response(301, req.uri)
55
-
56
- expect { redirector.perform(req, res) { res } }.
57
- to raise_error HTTP::Redirector::EndlessRedirectError
58
- end
59
-
60
- it "fails with StateError if there were no Location header" do
61
- req = HTTP::Request.new :verb => :head, :uri => "http://example.com"
62
- res = simple_response(301)
63
-
64
- expect { |b| redirector.perform(req, res, &b) }.
65
- to raise_error HTTP::StateError
66
- end
67
-
68
- it "returns first non-redirect response" do
69
- req = HTTP::Request.new :verb => :head, :uri => "http://example.com"
70
- hops = [
71
- redirect_response(301, "http://example.com/1"),
72
- redirect_response(301, "http://example.com/2"),
73
- redirect_response(301, "http://example.com/3"),
74
- simple_response(200, "foo"),
75
- redirect_response(301, "http://example.com/4"),
76
- simple_response(200, "bar")
77
- ]
78
-
79
- res = redirector.perform(req, hops.shift) { hops.shift }
80
- expect(res.to_s).to eq "foo"
81
- end
82
-
83
- it "concatenates multiple Location headers" do
84
- req = HTTP::Request.new :verb => :head, :uri => "http://example.com"
85
- headers = HTTP::Headers.new
86
-
87
- %w[http://example.com /123].each { |loc| headers.add("Location", loc) }
88
-
89
- res = redirector.perform(req, simple_response(301, "", headers)) do |redirect|
90
- simple_response(200, redirect.uri.to_s)
91
- end
92
-
93
- expect(res.to_s).to eq "http://example.com/123"
94
- end
95
-
96
- it "returns cookies in response" do
97
- req = HTTP::Request.new :verb => :head, :uri => "http://example.com"
98
- hops = [
99
- redirect_response(301, "http://example.com/1", {"foo" => "42"}),
100
- redirect_response(301, "http://example.com/2", {"bar" => "53", "deleted" => "foo"}),
101
- redirect_response(301, "http://example.com/3", {"baz" => "64", "deleted" => ""}),
102
- redirect_response(301, "http://example.com/4", {"baz" => "65"}),
103
- simple_response(200, "bar")
104
- ]
105
-
106
- request_cookies = [
107
- {"foo" => "42"},
108
- {"foo" => "42", "bar" => "53", "deleted" => "foo"},
109
- {"foo" => "42", "bar" => "53", "baz" => "64"},
110
- {"foo" => "42", "bar" => "53", "baz" => "65"}
111
- ]
112
-
113
- res = redirector.perform(req, hops.shift) do |request|
114
- req_cookie = HTTP::Cookie.cookie_value_to_hash(request.headers["Cookie"] || "")
115
- expect(req_cookie).to eq request_cookies.shift
116
- hops.shift
117
- end
118
- expect(res.to_s).to eq "bar"
119
- cookies = res.cookies.cookies.to_h { |c| [c.name, c.value] }
120
- expect(cookies["foo"]).to eq "42"
121
- expect(cookies["bar"]).to eq "53"
122
- expect(cookies["baz"]).to eq "65"
123
- expect(cookies["deleted"]).to eq nil
124
- end
125
-
126
- it "returns original cookies in response" do
127
- req = HTTP::Request.new :verb => :head, :uri => "http://example.com"
128
- req.headers.set("Cookie", "foo=42; deleted=baz")
129
- hops = [
130
- redirect_response(301, "http://example.com/1", {"bar" => "64", "deleted" => ""}),
131
- simple_response(200, "bar")
132
- ]
133
-
134
- request_cookies = [
135
- {"foo" => "42", "bar" => "64"},
136
- {"foo" => "42", "bar" => "64"}
137
- ]
138
-
139
- res = redirector.perform(req, hops.shift) do |request|
140
- req_cookie = HTTP::Cookie.cookie_value_to_hash(request.headers["Cookie"] || "")
141
- expect(req_cookie).to eq request_cookies.shift
142
- hops.shift
143
- end
144
- expect(res.to_s).to eq "bar"
145
- cookies = res.cookies.cookies.to_h { |c| [c.name, c.value] }
146
- expect(cookies["foo"]).to eq "42"
147
- expect(cookies["bar"]).to eq "64"
148
- expect(cookies["deleted"]).to eq nil
149
- end
150
-
151
- context "with on_redirect callback" do
152
- let(:options) do
153
- {
154
- :on_redirect => proc do |response, location|
155
- @redirect_response = response
156
- @redirect_location = location
157
- end
158
- }
159
- end
160
-
161
- it "calls on_redirect" do
162
- req = HTTP::Request.new :verb => :head, :uri => "http://example.com"
163
- hops = [
164
- redirect_response(301, "http://example.com/1"),
165
- redirect_response(301, "http://example.com/2"),
166
- simple_response(200, "foo")
167
- ]
168
-
169
- redirector.perform(req, hops.shift) do |prev_req, _|
170
- expect(@redirect_location.uri.to_s).to eq prev_req.uri.to_s
171
- expect(@redirect_response.code).to eq 301
172
- hops.shift
173
- end
174
- end
175
- end
176
-
177
- context "following 300 redirect" do
178
- context "with strict mode" do
179
- let(:options) { {:strict => true} }
180
-
181
- it "it follows with original verb if it's safe" do
182
- req = HTTP::Request.new :verb => :head, :uri => "http://example.com"
183
- res = redirect_response 300, "http://example.com/1"
184
-
185
- redirector.perform(req, res) do |prev_req, _|
186
- expect(prev_req.verb).to be :head
187
- simple_response 200
188
- end
189
- end
190
-
191
- it "raises StateError if original request was PUT" do
192
- req = HTTP::Request.new :verb => :put, :uri => "http://example.com"
193
- res = redirect_response 300, "http://example.com/1"
194
-
195
- expect { redirector.perform(req, res) { simple_response 200 } }.
196
- to raise_error HTTP::StateError
197
- end
198
-
199
- it "raises StateError if original request was POST" do
200
- req = HTTP::Request.new :verb => :post, :uri => "http://example.com"
201
- res = redirect_response 300, "http://example.com/1"
202
-
203
- expect { redirector.perform(req, res) { simple_response 200 } }.
204
- to raise_error HTTP::StateError
205
- end
206
-
207
- it "raises StateError if original request was DELETE" do
208
- req = HTTP::Request.new :verb => :delete, :uri => "http://example.com"
209
- res = redirect_response 300, "http://example.com/1"
210
-
211
- expect { redirector.perform(req, res) { simple_response 200 } }.
212
- to raise_error HTTP::StateError
213
- end
214
- end
215
-
216
- context "with non-strict mode" do
217
- let(:options) { {:strict => false} }
218
-
219
- it "it follows with original verb if it's safe" do
220
- req = HTTP::Request.new :verb => :head, :uri => "http://example.com"
221
- res = redirect_response 300, "http://example.com/1"
222
-
223
- redirector.perform(req, res) do |prev_req, _|
224
- expect(prev_req.verb).to be :head
225
- simple_response 200
226
- end
227
- end
228
-
229
- it "it follows with GET if original request was PUT" do
230
- req = HTTP::Request.new :verb => :put, :uri => "http://example.com"
231
- res = redirect_response 300, "http://example.com/1"
232
-
233
- redirector.perform(req, res) do |prev_req, _|
234
- expect(prev_req.verb).to be :get
235
- simple_response 200
236
- end
237
- end
238
-
239
- it "it follows with GET if original request was POST" do
240
- req = HTTP::Request.new :verb => :post, :uri => "http://example.com"
241
- res = redirect_response 300, "http://example.com/1"
242
-
243
- redirector.perform(req, res) do |prev_req, _|
244
- expect(prev_req.verb).to be :get
245
- simple_response 200
246
- end
247
- end
248
-
249
- it "it follows with GET if original request was DELETE" do
250
- req = HTTP::Request.new :verb => :delete, :uri => "http://example.com"
251
- res = redirect_response 300, "http://example.com/1"
252
-
253
- redirector.perform(req, res) do |prev_req, _|
254
- expect(prev_req.verb).to be :get
255
- simple_response 200
256
- end
257
- end
258
- end
259
- end
260
-
261
- context "following 301 redirect" do
262
- context "with strict mode" do
263
- let(:options) { {:strict => true} }
264
-
265
- it "it follows with original verb if it's safe" do
266
- req = HTTP::Request.new :verb => :head, :uri => "http://example.com"
267
- res = redirect_response 301, "http://example.com/1"
268
-
269
- redirector.perform(req, res) do |prev_req, _|
270
- expect(prev_req.verb).to be :head
271
- simple_response 200
272
- end
273
- end
274
-
275
- it "raises StateError if original request was PUT" do
276
- req = HTTP::Request.new :verb => :put, :uri => "http://example.com"
277
- res = redirect_response 301, "http://example.com/1"
278
-
279
- expect { redirector.perform(req, res) { simple_response 200 } }.
280
- to raise_error HTTP::StateError
281
- end
282
-
283
- it "raises StateError if original request was POST" do
284
- req = HTTP::Request.new :verb => :post, :uri => "http://example.com"
285
- res = redirect_response 301, "http://example.com/1"
286
-
287
- expect { redirector.perform(req, res) { simple_response 200 } }.
288
- to raise_error HTTP::StateError
289
- end
290
-
291
- it "raises StateError if original request was DELETE" do
292
- req = HTTP::Request.new :verb => :delete, :uri => "http://example.com"
293
- res = redirect_response 301, "http://example.com/1"
294
-
295
- expect { redirector.perform(req, res) { simple_response 200 } }.
296
- to raise_error HTTP::StateError
297
- end
298
- end
299
-
300
- context "with non-strict mode" do
301
- let(:options) { {:strict => false} }
302
-
303
- it "it follows with original verb if it's safe" do
304
- req = HTTP::Request.new :verb => :head, :uri => "http://example.com"
305
- res = redirect_response 301, "http://example.com/1"
306
-
307
- redirector.perform(req, res) do |prev_req, _|
308
- expect(prev_req.verb).to be :head
309
- simple_response 200
310
- end
311
- end
312
-
313
- it "it follows with GET if original request was PUT" do
314
- req = HTTP::Request.new :verb => :put, :uri => "http://example.com"
315
- res = redirect_response 301, "http://example.com/1"
316
-
317
- redirector.perform(req, res) do |prev_req, _|
318
- expect(prev_req.verb).to be :get
319
- simple_response 200
320
- end
321
- end
322
-
323
- it "it follows with GET if original request was POST" do
324
- req = HTTP::Request.new :verb => :post, :uri => "http://example.com"
325
- res = redirect_response 301, "http://example.com/1"
326
-
327
- redirector.perform(req, res) do |prev_req, _|
328
- expect(prev_req.verb).to be :get
329
- simple_response 200
330
- end
331
- end
332
-
333
- it "it follows with GET if original request was DELETE" do
334
- req = HTTP::Request.new :verb => :delete, :uri => "http://example.com"
335
- res = redirect_response 301, "http://example.com/1"
336
-
337
- redirector.perform(req, res) do |prev_req, _|
338
- expect(prev_req.verb).to be :get
339
- simple_response 200
340
- end
341
- end
342
- end
343
- end
344
-
345
- context "following 302 redirect" do
346
- context "with strict mode" do
347
- let(:options) { {:strict => true} }
348
-
349
- it "it follows with original verb if it's safe" do
350
- req = HTTP::Request.new :verb => :head, :uri => "http://example.com"
351
- res = redirect_response 302, "http://example.com/1"
352
-
353
- redirector.perform(req, res) do |prev_req, _|
354
- expect(prev_req.verb).to be :head
355
- simple_response 200
356
- end
357
- end
358
-
359
- it "raises StateError if original request was PUT" do
360
- req = HTTP::Request.new :verb => :put, :uri => "http://example.com"
361
- res = redirect_response 302, "http://example.com/1"
362
-
363
- expect { redirector.perform(req, res) { simple_response 200 } }.
364
- to raise_error HTTP::StateError
365
- end
366
-
367
- it "raises StateError if original request was POST" do
368
- req = HTTP::Request.new :verb => :post, :uri => "http://example.com"
369
- res = redirect_response 302, "http://example.com/1"
370
-
371
- expect { redirector.perform(req, res) { simple_response 200 } }.
372
- to raise_error HTTP::StateError
373
- end
374
-
375
- it "raises StateError if original request was DELETE" do
376
- req = HTTP::Request.new :verb => :delete, :uri => "http://example.com"
377
- res = redirect_response 302, "http://example.com/1"
378
-
379
- expect { redirector.perform(req, res) { simple_response 200 } }.
380
- to raise_error HTTP::StateError
381
- end
382
- end
383
-
384
- context "with non-strict mode" do
385
- let(:options) { {:strict => false} }
386
-
387
- it "it follows with original verb if it's safe" do
388
- req = HTTP::Request.new :verb => :head, :uri => "http://example.com"
389
- res = redirect_response 302, "http://example.com/1"
390
-
391
- redirector.perform(req, res) do |prev_req, _|
392
- expect(prev_req.verb).to be :head
393
- simple_response 200
394
- end
395
- end
396
-
397
- it "it follows with GET if original request was PUT" do
398
- req = HTTP::Request.new :verb => :put, :uri => "http://example.com"
399
- res = redirect_response 302, "http://example.com/1"
400
-
401
- redirector.perform(req, res) do |prev_req, _|
402
- expect(prev_req.verb).to be :get
403
- simple_response 200
404
- end
405
- end
406
-
407
- it "it follows with GET if original request was POST" do
408
- req = HTTP::Request.new :verb => :post, :uri => "http://example.com"
409
- res = redirect_response 302, "http://example.com/1"
410
-
411
- redirector.perform(req, res) do |prev_req, _|
412
- expect(prev_req.verb).to be :get
413
- simple_response 200
414
- end
415
- end
416
-
417
- it "it follows with GET if original request was DELETE" do
418
- req = HTTP::Request.new :verb => :delete, :uri => "http://example.com"
419
- res = redirect_response 302, "http://example.com/1"
420
-
421
- redirector.perform(req, res) do |prev_req, _|
422
- expect(prev_req.verb).to be :get
423
- simple_response 200
424
- end
425
- end
426
- end
427
- end
428
-
429
- context "following 303 redirect" do
430
- it "follows with HEAD if original request was HEAD" do
431
- req = HTTP::Request.new :verb => :head, :uri => "http://example.com"
432
- res = redirect_response 303, "http://example.com/1"
433
-
434
- redirector.perform(req, res) do |prev_req, _|
435
- expect(prev_req.verb).to be :head
436
- simple_response 200
437
- end
438
- end
439
-
440
- it "follows with GET if original request was GET" do
441
- req = HTTP::Request.new :verb => :get, :uri => "http://example.com"
442
- res = redirect_response 303, "http://example.com/1"
443
-
444
- redirector.perform(req, res) do |prev_req, _|
445
- expect(prev_req.verb).to be :get
446
- simple_response 200
447
- end
448
- end
449
-
450
- it "follows with GET if original request was neither GET nor HEAD" do
451
- req = HTTP::Request.new :verb => :post, :uri => "http://example.com"
452
- res = redirect_response 303, "http://example.com/1"
453
-
454
- redirector.perform(req, res) do |prev_req, _|
455
- expect(prev_req.verb).to be :get
456
- simple_response 200
457
- end
458
- end
459
- end
460
-
461
- context "following 307 redirect" do
462
- it "follows with original request's verb" do
463
- req = HTTP::Request.new :verb => :post, :uri => "http://example.com"
464
- res = redirect_response 307, "http://example.com/1"
465
-
466
- redirector.perform(req, res) do |prev_req, _|
467
- expect(prev_req.verb).to be :post
468
- simple_response 200
469
- end
470
- end
471
- end
472
-
473
- context "following 308 redirect" do
474
- it "follows with original request's verb" do
475
- req = HTTP::Request.new :verb => :post, :uri => "http://example.com"
476
- res = redirect_response 308, "http://example.com/1"
477
-
478
- redirector.perform(req, res) do |prev_req, _|
479
- expect(prev_req.verb).to be :post
480
- simple_response 200
481
- end
482
- end
483
- end
484
-
485
- describe "changing verbs during redirects" do
486
- let(:options) { {:strict => false} }
487
- let(:post_body) { HTTP::Request::Body.new("i might be way longer in real life") }
488
- let(:cookie) { "dont=eat my cookies" }
489
-
490
- def a_dangerous_request(verb)
491
- HTTP::Request.new(
492
- :verb => verb, :uri => "http://example.com",
493
- :body => post_body, :headers => {
494
- "Content-Type" => "meme",
495
- "Cookie" => cookie
496
- }
497
- )
498
- end
499
-
500
- def empty_body
501
- HTTP::Request::Body.new(nil)
502
- end
503
-
504
- it "follows without body/content type if it has to change verb" do
505
- req = a_dangerous_request(:post)
506
- res = redirect_response 302, "http://example.com/1"
507
-
508
- redirector.perform(req, res) do |prev_req, _|
509
- expect(prev_req.body).to eq(empty_body)
510
- expect(prev_req.headers["Cookie"]).to eq(cookie)
511
- expect(prev_req.headers["Content-Type"]).to eq(nil)
512
- simple_response 200
513
- end
514
- end
515
-
516
- it "leaves body/content-type intact if it does not have to change verb" do
517
- req = a_dangerous_request(:post)
518
- res = redirect_response 307, "http://example.com/1"
519
-
520
- redirector.perform(req, res) do |prev_req, _|
521
- expect(prev_req.body).to eq(post_body)
522
- expect(prev_req.headers["Cookie"]).to eq(cookie)
523
- expect(prev_req.headers["Content-Type"]).to eq("meme")
524
- simple_response 200
525
- end
526
- end
527
- end
528
- end
529
- end