http 5.3.1 → 6.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.
Files changed (201) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +241 -41
  3. data/LICENSE.txt +1 -1
  4. data/README.md +110 -13
  5. data/UPGRADING.md +491 -0
  6. data/http.gemspec +32 -29
  7. data/lib/http/base64.rb +11 -1
  8. data/lib/http/chainable/helpers.rb +62 -0
  9. data/lib/http/chainable/verbs.rb +136 -0
  10. data/lib/http/chainable.rb +232 -136
  11. data/lib/http/client.rb +158 -127
  12. data/lib/http/connection/internals.rb +141 -0
  13. data/lib/http/connection.rb +126 -97
  14. data/lib/http/content_type.rb +61 -6
  15. data/lib/http/errors.rb +25 -1
  16. data/lib/http/feature.rb +65 -5
  17. data/lib/http/features/auto_deflate.rb +124 -17
  18. data/lib/http/features/auto_inflate.rb +38 -15
  19. data/lib/http/features/caching/entry.rb +178 -0
  20. data/lib/http/features/caching/in_memory_store.rb +63 -0
  21. data/lib/http/features/caching.rb +216 -0
  22. data/lib/http/features/digest_auth.rb +234 -0
  23. data/lib/http/features/instrumentation.rb +97 -17
  24. data/lib/http/features/logging.rb +183 -5
  25. data/lib/http/features/normalize_uri.rb +17 -0
  26. data/lib/http/features/raise_error.rb +18 -3
  27. data/lib/http/form_data/composite_io.rb +106 -0
  28. data/lib/http/form_data/file.rb +95 -0
  29. data/lib/http/form_data/multipart/param.rb +62 -0
  30. data/lib/http/form_data/multipart.rb +106 -0
  31. data/lib/http/form_data/part.rb +52 -0
  32. data/lib/http/form_data/readable.rb +58 -0
  33. data/lib/http/form_data/urlencoded.rb +175 -0
  34. data/lib/http/form_data/version.rb +8 -0
  35. data/lib/http/form_data.rb +102 -0
  36. data/lib/http/headers/known.rb +3 -0
  37. data/lib/http/headers/normalizer.rb +17 -36
  38. data/lib/http/headers.rb +172 -65
  39. data/lib/http/mime_type/adapter.rb +24 -9
  40. data/lib/http/mime_type/json.rb +19 -4
  41. data/lib/http/mime_type.rb +21 -3
  42. data/lib/http/options/definitions.rb +189 -0
  43. data/lib/http/options.rb +172 -125
  44. data/lib/http/redirector.rb +80 -75
  45. data/lib/http/request/body.rb +87 -6
  46. data/lib/http/request/builder.rb +184 -0
  47. data/lib/http/request/proxy.rb +83 -0
  48. data/lib/http/request/writer.rb +76 -16
  49. data/lib/http/request.rb +214 -98
  50. data/lib/http/response/body.rb +103 -18
  51. data/lib/http/response/inflater.rb +35 -7
  52. data/lib/http/response/parser.rb +98 -4
  53. data/lib/http/response/status/reasons.rb +2 -4
  54. data/lib/http/response/status.rb +141 -31
  55. data/lib/http/response.rb +219 -61
  56. data/lib/http/retriable/delay_calculator.rb +38 -11
  57. data/lib/http/retriable/errors.rb +21 -0
  58. data/lib/http/retriable/performer.rb +82 -38
  59. data/lib/http/session.rb +280 -0
  60. data/lib/http/timeout/global.rb +147 -34
  61. data/lib/http/timeout/null.rb +155 -9
  62. data/lib/http/timeout/per_operation.rb +139 -18
  63. data/lib/http/uri/normalizer.rb +82 -0
  64. data/lib/http/uri/parsing.rb +182 -0
  65. data/lib/http/uri.rb +289 -124
  66. data/lib/http/version.rb +2 -1
  67. data/lib/http.rb +11 -2
  68. data/sig/deps.rbs +122 -0
  69. data/sig/http.rbs +1619 -0
  70. data/test/http/base64_test.rb +28 -0
  71. data/test/http/client_test.rb +739 -0
  72. data/test/http/connection_test.rb +1533 -0
  73. data/test/http/content_type_test.rb +190 -0
  74. data/test/http/errors_test.rb +28 -0
  75. data/test/http/feature_test.rb +49 -0
  76. data/test/http/features/auto_deflate_test.rb +317 -0
  77. data/test/http/features/auto_inflate_test.rb +213 -0
  78. data/test/http/features/caching_test.rb +942 -0
  79. data/test/http/features/digest_auth_test.rb +996 -0
  80. data/test/http/features/instrumentation_test.rb +246 -0
  81. data/test/http/features/logging_test.rb +654 -0
  82. data/test/http/features/normalize_uri_test.rb +41 -0
  83. data/test/http/features/raise_error_test.rb +77 -0
  84. data/test/http/form_data/composite_io_test.rb +215 -0
  85. data/test/http/form_data/file_test.rb +255 -0
  86. data/test/http/form_data/fixtures/the-http-gem.info +1 -0
  87. data/test/http/form_data/multipart_test.rb +303 -0
  88. data/test/http/form_data/part_test.rb +90 -0
  89. data/test/http/form_data/urlencoded_test.rb +164 -0
  90. data/test/http/form_data_test.rb +232 -0
  91. data/test/http/headers/normalizer_test.rb +93 -0
  92. data/test/http/headers_test.rb +888 -0
  93. data/test/http/mime_type/json_test.rb +39 -0
  94. data/test/http/mime_type_test.rb +150 -0
  95. data/test/http/options/base_uri_test.rb +148 -0
  96. data/test/http/options/body_test.rb +21 -0
  97. data/test/http/options/features_test.rb +38 -0
  98. data/test/http/options/form_test.rb +21 -0
  99. data/test/http/options/headers_test.rb +32 -0
  100. data/test/http/options/json_test.rb +21 -0
  101. data/test/http/options/merge_test.rb +78 -0
  102. data/test/http/options/new_test.rb +37 -0
  103. data/test/http/options/proxy_test.rb +32 -0
  104. data/test/http/options_test.rb +575 -0
  105. data/test/http/redirector_test.rb +639 -0
  106. data/test/http/request/body_test.rb +318 -0
  107. data/test/http/request/builder_test.rb +623 -0
  108. data/test/http/request/writer_test.rb +391 -0
  109. data/test/http/request_test.rb +1733 -0
  110. data/test/http/response/body_test.rb +292 -0
  111. data/test/http/response/parser_test.rb +105 -0
  112. data/test/http/response/status_test.rb +322 -0
  113. data/test/http/response_test.rb +502 -0
  114. data/test/http/retriable/delay_calculator_test.rb +194 -0
  115. data/test/http/retriable/errors_test.rb +71 -0
  116. data/test/http/retriable/performer_test.rb +551 -0
  117. data/test/http/session_test.rb +424 -0
  118. data/test/http/timeout/global_test.rb +239 -0
  119. data/test/http/timeout/null_test.rb +218 -0
  120. data/test/http/timeout/per_operation_test.rb +220 -0
  121. data/test/http/uri/normalizer_test.rb +89 -0
  122. data/test/http/uri_test.rb +1140 -0
  123. data/test/http/version_test.rb +15 -0
  124. data/test/http_test.rb +818 -0
  125. data/test/regression_tests.rb +27 -0
  126. data/test/support/dummy_server/encoding_routes.rb +47 -0
  127. data/test/support/dummy_server/routes.rb +201 -0
  128. data/test/support/dummy_server/servlet.rb +81 -0
  129. data/test/support/dummy_server.rb +200 -0
  130. data/{spec → test}/support/fakeio.rb +2 -2
  131. data/test/support/http_handling_shared/connection_reuse_tests.rb +97 -0
  132. data/test/support/http_handling_shared/timeout_tests.rb +134 -0
  133. data/test/support/http_handling_shared.rb +11 -0
  134. data/test/support/proxy_server.rb +207 -0
  135. data/test/support/servers/runner.rb +67 -0
  136. data/{spec → test}/support/simplecov.rb +11 -2
  137. data/test/support/ssl_helper.rb +108 -0
  138. data/test/test_helper.rb +38 -0
  139. metadata +108 -168
  140. data/.github/workflows/ci.yml +0 -67
  141. data/.gitignore +0 -15
  142. data/.rspec +0 -1
  143. data/.rubocop/layout.yml +0 -8
  144. data/.rubocop/metrics.yml +0 -4
  145. data/.rubocop/rspec.yml +0 -9
  146. data/.rubocop/style.yml +0 -32
  147. data/.rubocop.yml +0 -11
  148. data/.rubocop_todo.yml +0 -219
  149. data/.yardopts +0 -2
  150. data/CHANGES_OLD.md +0 -1002
  151. data/Gemfile +0 -51
  152. data/Guardfile +0 -18
  153. data/Rakefile +0 -64
  154. data/lib/http/headers/mixin.rb +0 -34
  155. data/lib/http/retriable/client.rb +0 -37
  156. data/logo.png +0 -0
  157. data/spec/lib/http/client_spec.rb +0 -556
  158. data/spec/lib/http/connection_spec.rb +0 -88
  159. data/spec/lib/http/content_type_spec.rb +0 -47
  160. data/spec/lib/http/features/auto_deflate_spec.rb +0 -77
  161. data/spec/lib/http/features/auto_inflate_spec.rb +0 -86
  162. data/spec/lib/http/features/instrumentation_spec.rb +0 -81
  163. data/spec/lib/http/features/logging_spec.rb +0 -65
  164. data/spec/lib/http/features/raise_error_spec.rb +0 -62
  165. data/spec/lib/http/headers/mixin_spec.rb +0 -36
  166. data/spec/lib/http/headers/normalizer_spec.rb +0 -52
  167. data/spec/lib/http/headers_spec.rb +0 -527
  168. data/spec/lib/http/options/body_spec.rb +0 -15
  169. data/spec/lib/http/options/features_spec.rb +0 -33
  170. data/spec/lib/http/options/form_spec.rb +0 -15
  171. data/spec/lib/http/options/headers_spec.rb +0 -24
  172. data/spec/lib/http/options/json_spec.rb +0 -15
  173. data/spec/lib/http/options/merge_spec.rb +0 -68
  174. data/spec/lib/http/options/new_spec.rb +0 -30
  175. data/spec/lib/http/options/proxy_spec.rb +0 -20
  176. data/spec/lib/http/options_spec.rb +0 -13
  177. data/spec/lib/http/redirector_spec.rb +0 -530
  178. data/spec/lib/http/request/body_spec.rb +0 -211
  179. data/spec/lib/http/request/writer_spec.rb +0 -121
  180. data/spec/lib/http/request_spec.rb +0 -234
  181. data/spec/lib/http/response/body_spec.rb +0 -85
  182. data/spec/lib/http/response/parser_spec.rb +0 -74
  183. data/spec/lib/http/response/status_spec.rb +0 -253
  184. data/spec/lib/http/response_spec.rb +0 -262
  185. data/spec/lib/http/retriable/delay_calculator_spec.rb +0 -69
  186. data/spec/lib/http/retriable/performer_spec.rb +0 -302
  187. data/spec/lib/http/uri/normalizer_spec.rb +0 -95
  188. data/spec/lib/http/uri_spec.rb +0 -71
  189. data/spec/lib/http_spec.rb +0 -535
  190. data/spec/regression_specs.rb +0 -24
  191. data/spec/spec_helper.rb +0 -89
  192. data/spec/support/black_hole.rb +0 -13
  193. data/spec/support/dummy_server/servlet.rb +0 -203
  194. data/spec/support/dummy_server.rb +0 -44
  195. data/spec/support/fuubar.rb +0 -21
  196. data/spec/support/http_handling_shared.rb +0 -190
  197. data/spec/support/proxy_server.rb +0 -39
  198. data/spec/support/servers/config.rb +0 -11
  199. data/spec/support/servers/runner.rb +0 -19
  200. data/spec/support/ssl_helper.rb +0 -104
  201. /data/{spec → test}/support/capture_warning.rb +0 -0
@@ -1,535 +0,0 @@
1
- # encoding: utf-8
2
- # frozen_string_literal: true
3
-
4
- require "json"
5
-
6
- require "support/dummy_server"
7
- require "support/proxy_server"
8
-
9
- RSpec.describe HTTP do
10
- run_server(:dummy) { DummyServer.new }
11
- run_server(:dummy_ssl) { DummyServer.new(:ssl => true) }
12
-
13
- let(:ssl_client) do
14
- HTTP::Client.new :ssl_context => SSLHelper.client_context
15
- end
16
-
17
- context "getting resources" do
18
- it "is easy" do
19
- response = HTTP.get dummy.endpoint
20
- expect(response.to_s).to match(/<!doctype html>/)
21
- end
22
-
23
- context "with URI instance" do
24
- it "is easy" do
25
- response = HTTP.get HTTP::URI.parse dummy.endpoint
26
- expect(response.to_s).to match(/<!doctype html>/)
27
- end
28
- end
29
-
30
- context "with query string parameters" do
31
- it "is easy" do
32
- response = HTTP.get "#{dummy.endpoint}/params", :params => {:foo => "bar"}
33
- expect(response.to_s).to match(/Params!/)
34
- end
35
- end
36
-
37
- context "with query string parameters in the URI and opts hash" do
38
- it "includes both" do
39
- response = HTTP.get "#{dummy.endpoint}/multiple-params?foo=bar", :params => {:baz => "quux"}
40
- expect(response.to_s).to match(/More Params!/)
41
- end
42
- end
43
-
44
- context "with two leading slashes in path" do
45
- it "is allowed" do
46
- expect { HTTP.get "#{dummy.endpoint}//" }.not_to raise_error
47
- end
48
- end
49
-
50
- context "with headers" do
51
- it "is easy" do
52
- response = HTTP.accept("application/json").get dummy.endpoint
53
- expect(response.to_s.include?("json")).to be true
54
- end
55
- end
56
-
57
- context "with a large request body" do
58
- let(:request_body) { "“" * 1_000_000 } # use multi-byte character
59
-
60
- [:null, 6, {:read => 2, :write => 2, :connect => 2}].each do |timeout|
61
- context "with `.timeout(#{timeout.inspect})`" do
62
- let(:client) { HTTP.timeout(timeout) }
63
-
64
- it "writes the whole body" do
65
- response = client.post "#{dummy.endpoint}/echo-body", :body => request_body
66
-
67
- expect(response.body.to_s).to eq(request_body.b)
68
- expect(response.headers["Content-Length"].to_i).to eq request_body.bytesize
69
- end
70
- end
71
- end
72
- end
73
- end
74
-
75
- describe ".via" do
76
- context "anonymous proxy" do
77
- run_server(:proxy) { ProxyServer.new }
78
-
79
- it "proxies the request" do
80
- response = HTTP.via(proxy.addr, proxy.port).get dummy.endpoint
81
- expect(response.headers["X-Proxied"]).to eq "true"
82
- end
83
-
84
- it "responds with the endpoint's body" do
85
- response = HTTP.via(proxy.addr, proxy.port).get dummy.endpoint
86
- expect(response.to_s).to match(/<!doctype html>/)
87
- end
88
-
89
- it "raises an argument error if no port given" do
90
- expect { HTTP.via(proxy.addr) }.to raise_error HTTP::RequestError
91
- end
92
-
93
- it "ignores credentials" do
94
- response = HTTP.via(proxy.addr, proxy.port, "username", "password").get dummy.endpoint
95
- expect(response.to_s).to match(/<!doctype html>/)
96
- end
97
-
98
- # TODO: htt:s://github.com/httprb/http/issues/627
99
- xcontext "ssl" do
100
- it "responds with the endpoint's body" do
101
- response = ssl_client.via(proxy.addr, proxy.port).get dummy_ssl.endpoint
102
- expect(response.to_s).to match(/<!doctype html>/)
103
- end
104
-
105
- it "ignores credentials" do
106
- response = ssl_client.via(proxy.addr, proxy.port, "username", "password").get dummy_ssl.endpoint
107
- expect(response.to_s).to match(/<!doctype html>/)
108
- end
109
- end
110
- end
111
-
112
- context "proxy with authentication" do
113
- run_server(:proxy) { AuthProxyServer.new }
114
-
115
- it "proxies the request" do
116
- response = HTTP.via(proxy.addr, proxy.port, "username", "password").get dummy.endpoint
117
- expect(response.headers["X-Proxied"]).to eq "true"
118
- end
119
-
120
- it "responds with the endpoint's body" do
121
- response = HTTP.via(proxy.addr, proxy.port, "username", "password").get dummy.endpoint
122
- expect(response.to_s).to match(/<!doctype html>/)
123
- end
124
-
125
- it "responds with 407 when wrong credentials given" do
126
- response = HTTP.via(proxy.addr, proxy.port, "user", "pass").get dummy.endpoint
127
- expect(response.status).to eq(407)
128
- end
129
-
130
- it "responds with 407 if no credentials given" do
131
- response = HTTP.via(proxy.addr, proxy.port).get dummy.endpoint
132
- expect(response.status).to eq(407)
133
- end
134
-
135
- # TODO: htt:s://github.com/httprb/http/issues/627
136
- xcontext "ssl" do
137
- it "responds with the endpoint's body" do
138
- response = ssl_client.via(proxy.addr, proxy.port, "username", "password").get dummy_ssl.endpoint
139
- expect(response.to_s).to match(/<!doctype html>/)
140
- end
141
-
142
- it "responds with 407 when wrong credentials given" do
143
- response = ssl_client.via(proxy.addr, proxy.port, "user", "pass").get dummy_ssl.endpoint
144
- expect(response.status).to eq(407)
145
- end
146
-
147
- it "responds with 407 if no credentials given" do
148
- response = ssl_client.via(proxy.addr, proxy.port).get dummy_ssl.endpoint
149
- expect(response.status).to eq(407)
150
- end
151
- end
152
- end
153
- end
154
-
155
- describe ".retry" do
156
- it "ensure endpoint counts retries" do
157
- expect(HTTP.get("#{dummy.endpoint}/retry-2").to_s).to eq "retried 1x"
158
- expect(HTTP.get("#{dummy.endpoint}/retry-2").to_s).to eq "retried 2x"
159
- end
160
-
161
- it "retries the request" do
162
- response = HTTP.retriable(delay: 0, retry_statuses: 500...600).get "#{dummy.endpoint}/retry-2"
163
- expect(response.to_s).to eq "retried 2x"
164
- end
165
-
166
- it "retries the request and gives us access to the failed requests" do
167
- err = nil
168
- retry_callback = ->(_, _, res) { expect(res.to_s).to match(/^retried \dx$/) }
169
- begin
170
- HTTP.retriable(
171
- should_retry: ->(*) { true },
172
- tries: 3,
173
- delay: 0,
174
- on_retry: retry_callback
175
- ).get "#{dummy.endpoint}/retry-2"
176
- rescue HTTP::Error => e
177
- err = e
178
- end
179
-
180
- expect(err.response.to_s).to eq "retried 3x"
181
- end
182
- end
183
-
184
- context "posting forms to resources" do
185
- it "is easy" do
186
- response = HTTP.post "#{dummy.endpoint}/form", :form => {:example => "testing-form"}
187
- expect(response.to_s).to eq("passed :)")
188
- end
189
- end
190
-
191
- context "loading binary data" do
192
- it "is encoded as bytes" do
193
- response = HTTP.get "#{dummy.endpoint}/bytes"
194
- expect(response.to_s.encoding).to eq(Encoding::BINARY)
195
- end
196
- end
197
-
198
- context "loading endpoint with charset" do
199
- it "uses charset from headers" do
200
- response = HTTP.get "#{dummy.endpoint}/iso-8859-1"
201
- expect(response.to_s.encoding).to eq(Encoding::ISO8859_1)
202
- expect(response.to_s.encode(Encoding::UTF_8)).to eq("testæ")
203
- end
204
-
205
- context "with encoding option" do
206
- it "respects option" do
207
- response = HTTP.get "#{dummy.endpoint}/iso-8859-1", :encoding => Encoding::BINARY
208
- expect(response.to_s.encoding).to eq(Encoding::BINARY)
209
- end
210
- end
211
- end
212
-
213
- context "passing a string encoding type" do
214
- it "finds encoding" do
215
- response = HTTP.get dummy.endpoint, :encoding => "ascii"
216
- expect(response.to_s.encoding).to eq(Encoding::ASCII)
217
- end
218
- end
219
-
220
- context "loading text with no charset" do
221
- it "is binary encoded" do
222
- response = HTTP.get dummy.endpoint
223
- expect(response.to_s.encoding).to eq(Encoding::BINARY)
224
- end
225
- end
226
-
227
- context "posting with an explicit body" do
228
- it "is easy" do
229
- response = HTTP.post "#{dummy.endpoint}/body", :body => "testing-body"
230
- expect(response.to_s).to eq("passed :)")
231
- end
232
- end
233
-
234
- context "with redirects" do
235
- it "is easy for 301" do
236
- response = HTTP.follow.get("#{dummy.endpoint}/redirect-301")
237
- expect(response.to_s).to match(/<!doctype html>/)
238
- end
239
-
240
- it "is easy for 302" do
241
- response = HTTP.follow.get("#{dummy.endpoint}/redirect-302")
242
- expect(response.to_s).to match(/<!doctype html>/)
243
- end
244
- end
245
-
246
- context "head requests" do
247
- it "is easy" do
248
- response = HTTP.head dummy.endpoint
249
- expect(response.status).to eq(200)
250
- expect(response["content-type"]).to match(/html/)
251
- end
252
- end
253
-
254
- describe ".auth" do
255
- it "sets Authorization header to the given value" do
256
- client = HTTP.auth "abc"
257
- expect(client.default_options.headers[:authorization]).to eq "abc"
258
- end
259
-
260
- it "accepts any #to_s object" do
261
- client = HTTP.auth double :to_s => "abc"
262
- expect(client.default_options.headers[:authorization]).to eq "abc"
263
- end
264
- end
265
-
266
- describe ".basic_auth" do
267
- it "fails when options is not a Hash" do
268
- expect { HTTP.basic_auth "[FOOBAR]" }.to raise_error(NoMethodError)
269
- end
270
-
271
- it "fails when :pass is not given" do
272
- expect { HTTP.basic_auth :user => "[USER]" }.to raise_error(KeyError)
273
- end
274
-
275
- it "fails when :user is not given" do
276
- expect { HTTP.basic_auth :pass => "[PASS]" }.to raise_error(KeyError)
277
- end
278
-
279
- it "sets Authorization header with proper BasicAuth value" do
280
- client = HTTP.basic_auth :user => "foo", :pass => "bar"
281
- expect(client.default_options.headers[:authorization]).
282
- to match(%r{^Basic [A-Za-z0-9+/]+=*$})
283
- end
284
- end
285
-
286
- describe ".persistent" do
287
- let(:host) { "https://api.github.com" }
288
-
289
- context "with host only given" do
290
- subject { HTTP.persistent host }
291
- it { is_expected.to be_an HTTP::Client }
292
- it { is_expected.to be_persistent }
293
- end
294
-
295
- context "with host and block given" do
296
- it "returns last evaluation of last expression" do
297
- expect(HTTP.persistent(host) { :http }).to be :http
298
- end
299
-
300
- it "auto-closes connection" do
301
- HTTP.persistent host do |client|
302
- expect(client).to receive(:close).and_call_original
303
- client.get("/repos/httprb/http.rb")
304
- end
305
- end
306
- end
307
-
308
- context "with timeout specified" do
309
- subject(:client) { HTTP.persistent host, :timeout => 100 }
310
- it "sets keep_alive_timeout" do
311
- options = client.default_options
312
- expect(options.keep_alive_timeout).to eq(100)
313
- end
314
- end
315
- end
316
-
317
- describe ".timeout" do
318
- context "specifying a null timeout" do
319
- subject(:client) { HTTP.timeout :null }
320
-
321
- it "sets timeout_class to Null" do
322
- expect(client.default_options.timeout_class).
323
- to be HTTP::Timeout::Null
324
- end
325
- end
326
-
327
- context "specifying per operation timeouts" do
328
- subject(:client) { HTTP.timeout :read => 123 }
329
-
330
- it "sets timeout_class to PerOperation" do
331
- expect(client.default_options.timeout_class).
332
- to be HTTP::Timeout::PerOperation
333
- end
334
-
335
- it "sets given timeout options" do
336
- expect(client.default_options.timeout_options).
337
- to eq :read_timeout => 123
338
- end
339
- end
340
-
341
- context "specifying per operation timeouts as frozen hash" do
342
- let(:frozen_options) { {:read => 123}.freeze }
343
- subject(:client) { HTTP.timeout(frozen_options) }
344
-
345
- it "does not raise an error" do
346
- expect { client }.not_to raise_error
347
- end
348
- end
349
-
350
- context "specifying a global timeout" do
351
- subject(:client) { HTTP.timeout 123 }
352
-
353
- it "sets timeout_class to Global" do
354
- expect(client.default_options.timeout_class).
355
- to be HTTP::Timeout::Global
356
- end
357
-
358
- it "sets given timeout option" do
359
- expect(client.default_options.timeout_options).
360
- to eq :global_timeout => 123
361
- end
362
- end
363
- end
364
-
365
- describe ".cookies" do
366
- let(:endpoint) { "#{dummy.endpoint}/cookies" }
367
-
368
- it "passes correct `Cookie` header" do
369
- expect(HTTP.cookies(:abc => :def).get(endpoint).to_s).
370
- to eq "abc: def"
371
- end
372
-
373
- it "properly works with cookie jars from response" do
374
- res = HTTP.get(endpoint).flush
375
-
376
- expect(HTTP.cookies(res.cookies).get(endpoint).to_s).
377
- to eq "foo: bar"
378
- end
379
-
380
- it "properly merges cookies" do
381
- res = HTTP.get(endpoint).flush
382
- client = HTTP.cookies(:foo => 123, :bar => 321).cookies(res.cookies)
383
-
384
- expect(client.get(endpoint).to_s).to eq "foo: bar\nbar: 321"
385
- end
386
-
387
- it "properly merges Cookie headers and cookies" do
388
- client = HTTP.headers("Cookie" => "foo=bar").cookies(:baz => :moo)
389
- expect(client.get(endpoint).to_s).to eq "foo: bar\nbaz: moo"
390
- end
391
- end
392
-
393
- describe ".nodelay" do
394
- before do
395
- HTTP.default_options = {:socket_class => socket_spy_class}
396
- end
397
-
398
- after do
399
- HTTP.default_options = {}
400
- end
401
-
402
- let(:socket_spy_class) do
403
- Class.new(TCPSocket) do
404
- def self.setsockopt_calls
405
- @setsockopt_calls ||= []
406
- end
407
-
408
- def setsockopt(*args)
409
- self.class.setsockopt_calls << args
410
- super
411
- end
412
- end
413
- end
414
-
415
- it "sets TCP_NODELAY on the underlying socket" do
416
- HTTP.get(dummy.endpoint)
417
- expect(socket_spy_class.setsockopt_calls).to eq([])
418
- HTTP.nodelay.get(dummy.endpoint)
419
- expect(socket_spy_class.setsockopt_calls).to eq([[Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1]])
420
- end
421
- end
422
-
423
- describe ".use" do
424
- it "turns on given feature" do
425
- client = HTTP.use :auto_deflate
426
- expect(client.default_options.features.keys).to eq [:auto_deflate]
427
- end
428
-
429
- context "with :auto_deflate" do
430
- it "sends gzipped body" do
431
- client = HTTP.use :auto_deflate
432
- body = "Hello!"
433
- response = client.post("#{dummy.endpoint}/echo-body", :body => body)
434
- encoded = response.to_s
435
-
436
- expect(Zlib::GzipReader.new(StringIO.new(encoded)).read).to eq body
437
- end
438
-
439
- it "sends deflated body" do
440
- client = HTTP.use :auto_deflate => {:method => "deflate"}
441
- body = "Hello!"
442
- response = client.post("#{dummy.endpoint}/echo-body", :body => body)
443
- encoded = response.to_s
444
-
445
- expect(Zlib::Inflate.inflate(encoded)).to eq body
446
- end
447
- end
448
-
449
- context "with :auto_inflate" do
450
- it "returns raw body when Content-Encoding type is missing" do
451
- client = HTTP.use :auto_inflate
452
- body = "Hello!"
453
- response = client.post("#{dummy.endpoint}/encoded-body", :body => body)
454
- expect(response.to_s).to eq("#{body}-raw")
455
- end
456
-
457
- it "returns decoded body" do
458
- client = HTTP.use(:auto_inflate).headers("Accept-Encoding" => "gzip")
459
- body = "Hello!"
460
- response = client.post("#{dummy.endpoint}/encoded-body", :body => body)
461
-
462
- expect(response.to_s).to eq("#{body}-gzipped")
463
- end
464
-
465
- it "returns deflated body" do
466
- client = HTTP.use(:auto_inflate).headers("Accept-Encoding" => "deflate")
467
- body = "Hello!"
468
- response = client.post("#{dummy.endpoint}/encoded-body", :body => body)
469
-
470
- expect(response.to_s).to eq("#{body}-deflated")
471
- end
472
-
473
- it "returns empty body for no content response where Content-Encoding is gzip" do
474
- client = HTTP.use(:auto_inflate).headers("Accept-Encoding" => "gzip")
475
- body = "Hello!"
476
- response = client.post("#{dummy.endpoint}/no-content-204", :body => body)
477
-
478
- expect(response.to_s).to eq("")
479
- end
480
-
481
- it "returns empty body for no content response where Content-Encoding is deflate" do
482
- client = HTTP.use(:auto_inflate).headers("Accept-Encoding" => "deflate")
483
- body = "Hello!"
484
- response = client.post("#{dummy.endpoint}/no-content-204", :body => body)
485
-
486
- expect(response.to_s).to eq("")
487
- end
488
- end
489
-
490
- context "with :normalize_uri" do
491
- it "normalizes URI" do
492
- response = HTTP.get "#{dummy.endpoint}/héllö-wörld"
493
- expect(response.to_s).to eq("hello world")
494
- end
495
-
496
- it "uses the custom URI Normalizer method" do
497
- client = HTTP.use(:normalize_uri => {:normalizer => :itself.to_proc})
498
- response = client.get("#{dummy.endpoint}/héllö-wörld")
499
- expect(response.status).to eq(400)
500
- end
501
-
502
- it "raises if custom URI Normalizer returns invalid path" do
503
- client = HTTP.use(:normalize_uri => {:normalizer => :itself.to_proc})
504
- expect { client.get("#{dummy.endpoint}/hello\nworld") }.
505
- to raise_error HTTP::RequestError, 'Invalid request URI: "/hello\nworld"'
506
- end
507
-
508
- it "raises if custom URI Normalizer returns invalid host" do
509
- normalizer = lambda do |uri|
510
- uri.port = nil
511
- uri.instance_variable_set(:@host, "example\ncom")
512
- uri
513
- end
514
- client = HTTP.use(:normalize_uri => {:normalizer => normalizer})
515
- expect { client.get(dummy.endpoint) }.
516
- to raise_error HTTP::RequestError, 'Invalid host: "example\ncom"'
517
- end
518
-
519
- it "uses the default URI normalizer" do
520
- client = HTTP.use :normalize_uri
521
- expect(HTTP::URI::NORMALIZER).to receive(:call).and_call_original
522
- response = client.get("#{dummy.endpoint}/héllö-wörld")
523
- expect(response.to_s).to eq("hello world")
524
- end
525
- end
526
- end
527
-
528
- it "unifies socket errors into HTTP::ConnectionError" do
529
- expect { HTTP.get "http://thishostshouldnotexists.com" }.
530
- to raise_error HTTP::ConnectionError
531
-
532
- expect { HTTP.get "http://127.0.0.1:111" }.
533
- to raise_error HTTP::ConnectionError
534
- end
535
- end
@@ -1,24 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "spec_helper"
4
-
5
- RSpec.describe "Regression testing" do
6
- describe "#248" do
7
- it "does not fail with github" do
8
- github_uri = "http://github.com/"
9
- expect { HTTP.get(github_uri).to_s }.not_to raise_error
10
- end
11
-
12
- it "does not fail with googleapis" do
13
- google_uri = "https://www.googleapis.com/oauth2/v1/userinfo?alt=json"
14
- expect { HTTP.get(google_uri).to_s }.not_to raise_error
15
- end
16
- end
17
-
18
- describe "#422" do
19
- it "reads body when 200 OK response contains Upgrade header" do
20
- res = HTTP.get("https://httpbin.org/response-headers?Upgrade=h2,h2c")
21
- expect(res.parse(:json)).to include("Upgrade" => "h2,h2c")
22
- end
23
- end
24
- end
data/spec/spec_helper.rb DELETED
@@ -1,89 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "./support/simplecov"
4
- require_relative "./support/fuubar" unless ENV["CI"]
5
-
6
- require "http"
7
- require "rspec/its"
8
- require "rspec/memory"
9
- require "support/capture_warning"
10
- require "support/fakeio"
11
-
12
- # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
13
- RSpec.configure do |config|
14
- config.expect_with :rspec do |expectations|
15
- # This option will default to `true` in RSpec 4. It makes the `description`
16
- # and `failure_message` of custom matchers include text for helper methods
17
- # defined using `chain`, e.g.:
18
- # be_bigger_than(2).and_smaller_than(4).description
19
- # # => "be bigger than 2 and smaller than 4"
20
- # ...rather than:
21
- # # => "be bigger than 2"
22
- expectations.include_chain_clauses_in_custom_matcher_descriptions = true
23
- end
24
-
25
- config.mock_with :rspec do |mocks|
26
- # Prevents you from mocking or stubbing a method that does not exist on
27
- # a real object. This is generally recommended, and will default to
28
- # `true` in RSpec 4.
29
- mocks.verify_partial_doubles = true
30
- end
31
-
32
- # This option will default to `:apply_to_host_groups` in RSpec 4 (and will
33
- # have no way to turn it off -- the option exists only for backwards
34
- # compatibility in RSpec 3). It causes shared context metadata to be
35
- # inherited by the metadata hash of host groups and examples, rather than
36
- # triggering implicit auto-inclusion in groups with matching metadata.
37
- config.shared_context_metadata_behavior = :apply_to_host_groups
38
-
39
- # These two settings work together to allow you to limit a spec run
40
- # to individual examples or groups you care about by tagging them with
41
- # `:focus` metadata. When nothing is tagged with `:focus`, all examples
42
- # get run.
43
- config.filter_run :focus
44
- config.filter_run_excluding :flaky if defined?(JRUBY_VERSION) && ENV["CI"]
45
- config.run_all_when_everything_filtered = true
46
-
47
- # This setting enables warnings. It's recommended, but in some cases may
48
- # be too noisy due to issues in dependencies.
49
- config.warnings = 0 == ENV["GUARD_RSPEC"].to_i
50
-
51
- # Allows RSpec to persist some state between runs in order to support
52
- # the `--only-failures` and `--next-failure` CLI options. We recommend
53
- # you configure your source control system to ignore this file.
54
- config.example_status_persistence_file_path = "spec/examples.txt"
55
-
56
- # Limits the available syntax to the non-monkey patched syntax that is
57
- # recommended. For more details, see:
58
- # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/
59
- # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
60
- # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode
61
- config.disable_monkey_patching!
62
-
63
- # Many RSpec users commonly either run the entire suite or an individual
64
- # file, and it's useful to allow more verbose output when running an
65
- # individual spec file.
66
- if config.files_to_run.one?
67
- # Use the documentation formatter for detailed output,
68
- # unless a formatter has already been configured
69
- # (e.g. via a command-line flag).
70
- config.default_formatter = "doc"
71
- end
72
-
73
- # Print the 10 slowest examples and example groups at the
74
- # end of the spec run, to help surface which specs are running
75
- # particularly slow.
76
- config.profile_examples = 10
77
-
78
- # Run specs in random order to surface order dependencies. If you find an
79
- # order dependency and want to debug it, you can fix the order by providing
80
- # the seed, which is printed after each run.
81
- # --seed 1234
82
- config.order = :random
83
-
84
- # Seed global randomization in this process using the `--seed` CLI option.
85
- # Setting this allows you to use `--seed` to deterministically reproduce
86
- # test failures related to randomization by passing the same `--seed` value
87
- # as the one that triggered the failure.
88
- Kernel.srand config.seed
89
- end
@@ -1,13 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module BlackHole
4
- class << self
5
- def method_missing(*)
6
- self
7
- end
8
-
9
- def respond_to_missing?(*)
10
- true
11
- end
12
- end
13
- end