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,77 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe HTTP::Features::AutoDeflate do
4
- subject { HTTP::Features::AutoDeflate.new }
5
-
6
- it "raises error for wrong type" do
7
- expect { HTTP::Features::AutoDeflate.new(:method => :wrong) }.
8
- to raise_error(HTTP::Error) { |error|
9
- expect(error.message).to eq("Only gzip and deflate methods are supported")
10
- }
11
- end
12
-
13
- it "accepts gzip method" do
14
- expect(HTTP::Features::AutoDeflate.new(:method => :gzip).method).to eq "gzip"
15
- end
16
-
17
- it "accepts deflate method" do
18
- expect(HTTP::Features::AutoDeflate.new(:method => :deflate).method).to eq "deflate"
19
- end
20
-
21
- it "accepts string as method" do
22
- expect(HTTP::Features::AutoDeflate.new(:method => "gzip").method).to eq "gzip"
23
- end
24
-
25
- it "uses gzip by default" do
26
- expect(subject.method).to eq("gzip")
27
- end
28
-
29
- describe "#deflated_body" do
30
- let(:body) { %w[bees cows] }
31
- let(:deflated_body) { subject.deflated_body(body) }
32
-
33
- context "when method is gzip" do
34
- subject { HTTP::Features::AutoDeflate.new(:method => :gzip) }
35
-
36
- it "returns object which yields gzipped content of the given body" do
37
- io = StringIO.new
38
- io.set_encoding(Encoding::BINARY)
39
- gzip = Zlib::GzipWriter.new(io)
40
- gzip.write("beescows")
41
- gzip.close
42
- gzipped = io.string
43
-
44
- expect(deflated_body.each.to_a.join).to eq gzipped
45
- end
46
-
47
- it "caches compressed content when size is called" do
48
- io = StringIO.new
49
- io.set_encoding(Encoding::BINARY)
50
- gzip = Zlib::GzipWriter.new(io)
51
- gzip.write("beescows")
52
- gzip.close
53
- gzipped = io.string
54
-
55
- expect(deflated_body.size).to eq gzipped.bytesize
56
- expect(deflated_body.each.to_a.join).to eq gzipped
57
- end
58
- end
59
-
60
- context "when method is deflate" do
61
- subject { HTTP::Features::AutoDeflate.new(:method => :deflate) }
62
-
63
- it "returns object which yields deflated content of the given body" do
64
- deflated = Zlib::Deflate.deflate("beescows")
65
-
66
- expect(deflated_body.each.to_a.join).to eq deflated
67
- end
68
-
69
- it "caches compressed content when size is called" do
70
- deflated = Zlib::Deflate.deflate("beescows")
71
-
72
- expect(deflated_body.size).to eq deflated.bytesize
73
- expect(deflated_body.each.to_a.join).to eq deflated
74
- end
75
- end
76
- end
77
- end
@@ -1,86 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe HTTP::Features::AutoInflate do
4
- subject(:feature) { HTTP::Features::AutoInflate.new }
5
-
6
- let(:connection) { double }
7
- let(:headers) { {} }
8
-
9
- let(:response) do
10
- HTTP::Response.new(
11
- :version => "1.1",
12
- :status => 200,
13
- :headers => headers,
14
- :connection => connection,
15
- :request => HTTP::Request.new(:verb => :get, :uri => "http://example.com")
16
- )
17
- end
18
-
19
- describe "#wrap_response" do
20
- subject(:result) { feature.wrap_response(response) }
21
-
22
- context "when there is no Content-Encoding header" do
23
- it "returns original request" do
24
- expect(result).to be response
25
- end
26
- end
27
-
28
- context "for identity Content-Encoding header" do
29
- let(:headers) { {:content_encoding => "identity"} }
30
-
31
- it "returns original request" do
32
- expect(result).to be response
33
- end
34
- end
35
-
36
- context "for unknown Content-Encoding header" do
37
- let(:headers) { {:content_encoding => "not-supported"} }
38
-
39
- it "returns original request" do
40
- expect(result).to be response
41
- end
42
- end
43
-
44
- context "for deflate Content-Encoding header" do
45
- let(:headers) { {:content_encoding => "deflate"} }
46
-
47
- it "returns a HTTP::Response wrapping the inflated response body" do
48
- expect(result.body).to be_instance_of HTTP::Response::Body
49
- end
50
- end
51
-
52
- context "for gzip Content-Encoding header" do
53
- let(:headers) { {:content_encoding => "gzip"} }
54
-
55
- it "returns a HTTP::Response wrapping the inflated response body" do
56
- expect(result.body).to be_instance_of HTTP::Response::Body
57
- end
58
- end
59
-
60
- context "for x-gzip Content-Encoding header" do
61
- let(:headers) { {:content_encoding => "x-gzip"} }
62
-
63
- it "returns a HTTP::Response wrapping the inflated response body" do
64
- expect(result.body).to be_instance_of HTTP::Response::Body
65
- end
66
- end
67
-
68
- # TODO(ixti): We should refactor API to either make uri non-optional,
69
- # or add reference to request into response object (better).
70
- context "when response has uri" do
71
- let(:response) do
72
- HTTP::Response.new(
73
- :version => "1.1",
74
- :status => 200,
75
- :headers => {:content_encoding => "gzip"},
76
- :connection => connection,
77
- :request => HTTP::Request.new(:verb => :get, :uri => "https://example.com")
78
- )
79
- end
80
-
81
- it "preserves uri in wrapped response" do
82
- expect(result.uri).to eq HTTP::URI.parse("https://example.com")
83
- end
84
- end
85
- end
86
- end
@@ -1,81 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe HTTP::Features::Instrumentation do
4
- subject(:feature) { HTTP::Features::Instrumentation.new(:instrumenter => instrumenter) }
5
-
6
- let(:instrumenter) { TestInstrumenter.new }
7
-
8
- before do
9
- test_instrumenter = Class.new(HTTP::Features::Instrumentation::NullInstrumenter) do
10
- attr_reader :output
11
-
12
- def initialize
13
- @output = {}
14
- end
15
-
16
- def start(_name, payload)
17
- output[:start] = payload
18
- end
19
-
20
- def finish(_name, payload)
21
- output[:finish] = payload
22
- end
23
- end
24
-
25
- stub_const("TestInstrumenter", test_instrumenter)
26
- end
27
-
28
- describe "logging the request" do
29
- let(:request) do
30
- HTTP::Request.new(
31
- :verb => :post,
32
- :uri => "https://example.com/",
33
- :headers => {:accept => "application/json"},
34
- :body => '{"hello": "world!"}'
35
- )
36
- end
37
-
38
- it "should log the request" do
39
- feature.wrap_request(request)
40
-
41
- expect(instrumenter.output[:start]).to eq(:request => request)
42
- end
43
- end
44
-
45
- describe "logging the response" do
46
- let(:response) do
47
- HTTP::Response.new(
48
- :version => "1.1",
49
- :status => 200,
50
- :headers => {:content_type => "application/json"},
51
- :body => '{"success": true}',
52
- :request => HTTP::Request.new(:verb => :get, :uri => "https://example.com")
53
- )
54
- end
55
-
56
- it "should log the response" do
57
- feature.wrap_response(response)
58
-
59
- expect(instrumenter.output[:finish]).to eq(:response => response)
60
- end
61
- end
62
-
63
- describe "logging errors" do
64
- let(:request) do
65
- HTTP::Request.new(
66
- :verb => :post,
67
- :uri => "https://example.com/",
68
- :headers => {:accept => "application/json"},
69
- :body => '{"hello": "world!"}'
70
- )
71
- end
72
-
73
- let(:error) { HTTP::TimeoutError.new }
74
-
75
- it "should log the error" do
76
- feature.on_error(request, error)
77
-
78
- expect(instrumenter.output[:finish]).to eq(:request => request, :error => error)
79
- end
80
- end
81
- end
@@ -1,65 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "logger"
4
-
5
- RSpec.describe HTTP::Features::Logging do
6
- subject(:feature) do
7
- logger = Logger.new(logdev)
8
- logger.formatter = ->(severity, _, _, message) { format("** %s **\n%s\n", severity, message) }
9
-
10
- described_class.new(:logger => logger)
11
- end
12
-
13
- let(:logdev) { StringIO.new }
14
-
15
- describe "logging the request" do
16
- let(:request) do
17
- HTTP::Request.new(
18
- :verb => :post,
19
- :uri => "https://example.com/",
20
- :headers => {:accept => "application/json"},
21
- :body => '{"hello": "world!"}'
22
- )
23
- end
24
-
25
- it "should log the request" do
26
- feature.wrap_request(request)
27
-
28
- expect(logdev.string).to eq <<~OUTPUT
29
- ** INFO **
30
- > POST https://example.com/
31
- ** DEBUG **
32
- Accept: application/json
33
- Host: example.com
34
- User-Agent: http.rb/#{HTTP::VERSION}
35
-
36
- {"hello": "world!"}
37
- OUTPUT
38
- end
39
- end
40
-
41
- describe "logging the response" do
42
- let(:response) do
43
- HTTP::Response.new(
44
- :version => "1.1",
45
- :status => 200,
46
- :headers => {:content_type => "application/json"},
47
- :body => '{"success": true}',
48
- :request => HTTP::Request.new(:verb => :get, :uri => "https://example.com")
49
- )
50
- end
51
-
52
- it "should log the response" do
53
- feature.wrap_response(response)
54
-
55
- expect(logdev.string).to eq <<~OUTPUT
56
- ** INFO **
57
- < 200 OK
58
- ** DEBUG **
59
- Content-Type: application/json
60
-
61
- {"success": true}
62
- OUTPUT
63
- end
64
- end
65
- end
@@ -1,36 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe HTTP::Headers::Mixin do
4
- let :dummy_class do
5
- Class.new do
6
- include HTTP::Headers::Mixin
7
-
8
- def initialize(headers)
9
- @headers = headers
10
- end
11
- end
12
- end
13
-
14
- let(:headers) { HTTP::Headers.new }
15
- let(:dummy) { dummy_class.new headers }
16
-
17
- describe "#headers" do
18
- it "returns @headers instance variable" do
19
- expect(dummy.headers).to be headers
20
- end
21
- end
22
-
23
- describe "#[]" do
24
- it "proxies to headers#[]" do
25
- expect(headers).to receive(:[]).with(:accept)
26
- dummy[:accept]
27
- end
28
- end
29
-
30
- describe "#[]=" do
31
- it "proxies to headers#[]" do
32
- expect(headers).to receive(:[]=).with(:accept, "text/plain")
33
- dummy[:accept] = "text/plain"
34
- end
35
- end
36
- end