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,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
@@ -1,10 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- def capture_warning
4
- old_stderr = $stderr
5
- $stderr = StringIO.new
6
- yield
7
- $stderr.string
8
- ensure
9
- $stderr = old_stderr
10
- end
@@ -1,190 +0,0 @@
1
- # encoding: UTF-8
2
- # frozen_string_literal: true
3
-
4
- require "cgi"
5
-
6
- class DummyServer < WEBrick::HTTPServer
7
- class Servlet < WEBrick::HTTPServlet::AbstractServlet # rubocop:disable Metrics/ClassLength
8
- def self.sockets
9
- @sockets ||= []
10
- end
11
-
12
- def not_found(req, res)
13
- res.status = 404
14
- res.body = "#{req.unparsed_uri} not found"
15
- end
16
-
17
- def self.handlers
18
- @handlers ||= {}
19
- end
20
-
21
- %w[get post head].each do |method|
22
- class_eval <<-RUBY, __FILE__, __LINE__ + 1
23
- def self.#{method}(path, &block)
24
- handlers["#{method}:\#{path}"] = block
25
- end
26
-
27
- def do_#{method.upcase}(req, res)
28
- handler = self.class.handlers["#{method}:\#{req.path}"]
29
- return instance_exec(req, res, &handler) if handler
30
- not_found(req, res)
31
- end
32
- RUBY
33
- end
34
-
35
- get "/" do |req, res|
36
- res.status = 200
37
-
38
- case req["Accept"]
39
- when "application/json"
40
- res["Content-Type"] = "application/json"
41
- res.body = '{"json": true}'
42
- else
43
- res["Content-Type"] = "text/html"
44
- res.body = "<!doctype html>"
45
- end
46
- end
47
-
48
- get "/sleep" do |_, res|
49
- sleep 2
50
-
51
- res.status = 200
52
- res.body = "hello"
53
- end
54
-
55
- post "/sleep" do |_, res|
56
- sleep 2
57
-
58
- res.status = 200
59
- res.body = "hello"
60
- end
61
-
62
- ["", "/1", "/2"].each do |path|
63
- get "/socket#{path}" do |req, res|
64
- self.class.sockets << req.instance_variable_get(:@socket)
65
- res.status = 200
66
- res.body = req.instance_variable_get(:@socket).object_id.to_s
67
- end
68
- end
69
-
70
- get "/params" do |req, res|
71
- next not_found(req, res) unless "foo=bar" == req.query_string
72
-
73
- res.status = 200
74
- res.body = "Params!"
75
- end
76
-
77
- get "/multiple-params" do |req, res|
78
- params = CGI.parse req.query_string
79
-
80
- next not_found(req, res) unless {"foo" => ["bar"], "baz" => ["quux"]} == params
81
-
82
- res.status = 200
83
- res.body = "More Params!"
84
- end
85
-
86
- get "/proxy" do |_req, res|
87
- res.status = 200
88
- res.body = "Proxy!"
89
- end
90
-
91
- get "/not-found" do |_req, res|
92
- res.status = 404
93
- res.body = "not found"
94
- end
95
-
96
- get "/redirect-301" do |_req, res|
97
- res.status = 301
98
- res["Location"] = "http://#{@server.config[:BindAddress]}:#{@server.config[:Port]}/"
99
- end
100
-
101
- get "/redirect-302" do |_req, res|
102
- res.status = 302
103
- res["Location"] = "http://#{@server.config[:BindAddress]}:#{@server.config[:Port]}/"
104
- end
105
-
106
- post "/form" do |req, res|
107
- if "testing-form" == req.query["example"]
108
- res.status = 200
109
- res.body = "passed :)"
110
- else
111
- res.status = 400
112
- res.body = "invalid! >:E"
113
- end
114
- end
115
-
116
- post "/body" do |req, res|
117
- if "testing-body" == req.body
118
- res.status = 200
119
- res.body = "passed :)"
120
- else
121
- res.status = 400
122
- res.body = "invalid! >:E"
123
- end
124
- end
125
-
126
- head "/" do |_req, res|
127
- res.status = 200
128
- res["Content-Type"] = "text/html"
129
- end
130
-
131
- get "/bytes" do |_req, res|
132
- bytes = [80, 75, 3, 4, 20, 0, 0, 0, 8, 0, 123, 104, 169, 70, 99, 243, 243]
133
- res["Content-Type"] = "application/octet-stream"
134
- res.body = bytes.pack("c*")
135
- end
136
-
137
- get "/iso-8859-1" do |_req, res|
138
- res["Content-Type"] = "text/plain; charset=ISO-8859-1"
139
- res.body = "testæ".encode(Encoding::ISO8859_1)
140
- end
141
-
142
- get "/cookies" do |req, res|
143
- res["Set-Cookie"] = "foo=bar"
144
- res.body = req.cookies.map { |c| [c.name, c.value].join ": " }.join("\n")
145
- end
146
-
147
- post "/echo-body" do |req, res|
148
- res.status = 200
149
- res.body = req.body
150
- end
151
-
152
- get "/héllö-wörld".b do |_req, res|
153
- res.status = 200
154
- res.body = "hello world"
155
- end
156
-
157
- post "/encoded-body" do |req, res|
158
- res.status = 200
159
-
160
- res.body = case req["Accept-Encoding"]
161
- when "gzip"
162
- res["Content-Encoding"] = "gzip"
163
- StringIO.open do |out|
164
- Zlib::GzipWriter.wrap(out) do |gz|
165
- gz.write "#{req.body}-gzipped"
166
- gz.finish
167
- out.tap(&:rewind).read
168
- end
169
- end
170
- when "deflate"
171
- res["Content-Encoding"] = "deflate"
172
- Zlib::Deflate.deflate("#{req.body}-deflated")
173
- else
174
- "#{req.body}-raw"
175
- end
176
- end
177
-
178
- post "/no-content-204" do |req, res|
179
- res.status = 204
180
- res.body = ""
181
-
182
- case req["Accept-Encoding"]
183
- when "gzip"
184
- res["Content-Encoding"] = "gzip"
185
- when "deflate"
186
- res["Content-Encoding"] = "deflate"
187
- end
188
- end
189
- end
190
- end
@@ -1,43 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "webrick"
4
- require "webrick/ssl"
5
-
6
- require "support/black_hole"
7
- require "support/dummy_server/servlet"
8
- require "support/servers/config"
9
- require "support/servers/runner"
10
- require "support/ssl_helper"
11
-
12
- class DummyServer < WEBrick::HTTPServer
13
- include ServerConfig
14
-
15
- CONFIG = {
16
- :BindAddress => "127.0.0.1",
17
- :Port => 0,
18
- :AccessLog => BlackHole,
19
- :Logger => BlackHole
20
- }.freeze
21
-
22
- SSL_CONFIG = CONFIG.merge(
23
- :SSLEnable => true,
24
- :SSLStartImmediately => true
25
- ).freeze
26
-
27
- def initialize(options = {})
28
- super(options[:ssl] ? SSL_CONFIG : CONFIG)
29
- mount("/", Servlet)
30
- end
31
-
32
- def endpoint
33
- "#{scheme}://#{addr}:#{port}"
34
- end
35
-
36
- def scheme
37
- config[:SSLEnable] ? "https" : "http"
38
- end
39
-
40
- def ssl_context
41
- @ssl_context ||= SSLHelper.server_context
42
- end
43
- end
@@ -1,21 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "stringio"
4
-
5
- class FakeIO
6
- def initialize(content)
7
- @io = StringIO.new(content)
8
- end
9
-
10
- def string
11
- @io.string
12
- end
13
-
14
- def read(*args)
15
- @io.read(*args)
16
- end
17
-
18
- def size
19
- @io.size
20
- end
21
- end
@@ -1,21 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "fuubar"
4
-
5
- RSpec.configure do |config|
6
- # Use Fuubar instafail-alike formatter, unless a formatter has already been
7
- # configured (e.g. via a command-line flag).
8
- config.default_formatter = "Fuubar"
9
-
10
- # Disable auto-refresh of the fuubar progress bar to avoid surprises during
11
- # debugiing. And simply because there's next to absolutely no point in having
12
- # this turned on.
13
- #
14
- # > By default fuubar will automatically refresh the bar (and therefore
15
- # > the ETA) every second. Unfortunately this doesn't play well with things
16
- # > like debuggers. When you're debugging, having a bar show up every second
17
- # > is undesireable.
18
- #
19
- # See: https://github.com/thekompanee/fuubar#disabling-auto-refresh
20
- config.fuubar_auto_refresh = false
21
- end
@@ -1,190 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.shared_context "HTTP handling" do
4
- context "without timeouts" do
5
- let(:options) { {:timeout_class => HTTP::Timeout::Null, :timeout_options => {}} }
6
-
7
- it "works" do
8
- expect(client.get(server.endpoint).body.to_s).to eq("<!doctype html>")
9
- end
10
- end
11
-
12
- context "with a per operation timeout" do
13
- let(:response) { client.get(server.endpoint).body.to_s }
14
-
15
- let(:options) do
16
- {
17
- :timeout_class => HTTP::Timeout::PerOperation,
18
- :timeout_options => {
19
- :connect_timeout => conn_timeout,
20
- :read_timeout => read_timeout,
21
- :write_timeout => write_timeout
22
- }
23
- }
24
- end
25
- let(:conn_timeout) { 1 }
26
- let(:read_timeout) { 1 }
27
- let(:write_timeout) { 1 }
28
-
29
- it "works" do
30
- expect(response).to eq("<!doctype html>")
31
- end
32
-
33
- context "connection" do
34
- context "of 1" do
35
- let(:conn_timeout) { 1 }
36
-
37
- it "does not time out" do
38
- expect { response }.to_not raise_error
39
- end
40
- end
41
- end
42
-
43
- context "read" do
44
- context "of 0" do
45
- let(:read_timeout) { 0 }
46
-
47
- it "times out", :flaky do
48
- expect { response }.to raise_error(HTTP::TimeoutError, /Read/i)
49
- end
50
- end
51
-
52
- context "of 2.5" do
53
- let(:read_timeout) { 2.5 }
54
-
55
- it "does not time out", :flaky do
56
- expect { client.get("#{server.endpoint}/sleep").body.to_s }.to_not raise_error
57
- end
58
- end
59
- end
60
- end
61
-
62
- context "with a global timeout" do
63
- let(:options) do
64
- {
65
- :timeout_class => HTTP::Timeout::Global,
66
- :timeout_options => {
67
- :global_timeout => global_timeout
68
- }
69
- }
70
- end
71
- let(:global_timeout) { 1 }
72
-
73
- let(:response) { client.get(server.endpoint).body.to_s }
74
-
75
- it "errors if connecting takes too long" do
76
- expect(TCPSocket).to receive(:open) do
77
- sleep 1.25
78
- end
79
-
80
- expect { response }.to raise_error(HTTP::ConnectTimeoutError, /execution/)
81
- end
82
-
83
- it "errors if reading takes too long" do
84
- expect { client.get("#{server.endpoint}/sleep").body.to_s }.
85
- to raise_error(HTTP::TimeoutError, /Timed out/)
86
- end
87
-
88
- context "it resets state when reusing connections" do
89
- let(:extra_options) { {:persistent => server.endpoint} }
90
-
91
- let(:global_timeout) { 2.5 }
92
-
93
- it "does not timeout", :flaky do
94
- client.get("#{server.endpoint}/sleep").body.to_s
95
- client.get("#{server.endpoint}/sleep").body.to_s
96
- end
97
- end
98
- end
99
-
100
- describe "connection reuse" do
101
- let(:sockets_used) do
102
- [
103
- client.get("#{server.endpoint}/socket/1").body.to_s,
104
- client.get("#{server.endpoint}/socket/2").body.to_s
105
- ]
106
- end
107
-
108
- context "when enabled" do
109
- let(:options) { {:persistent => server.endpoint} }
110
-
111
- context "without a host" do
112
- it "infers host from persistent config" do
113
- expect(client.get("/").body.to_s).to eq("<!doctype html>")
114
- end
115
- end
116
-
117
- it "re-uses the socket" do
118
- expect(sockets_used).to_not include("")
119
- expect(sockets_used.uniq.length).to eq(1)
120
- end
121
-
122
- context "on a mixed state" do
123
- it "re-opens the connection", :flaky do
124
- first_socket_id = client.get("#{server.endpoint}/socket/1").body.to_s
125
-
126
- client.instance_variable_set(:@state, :dirty)
127
-
128
- second_socket_id = client.get("#{server.endpoint}/socket/2").body.to_s
129
-
130
- expect(first_socket_id).to_not eq(second_socket_id)
131
- end
132
- end
133
-
134
- context "when trying to read a stale body" do
135
- it "errors" do
136
- client.get("#{server.endpoint}/not-found")
137
- expect { client.get(server.endpoint) }.to raise_error(HTTP::StateError, /Tried to send a request/)
138
- end
139
- end
140
-
141
- context "when reading a cached body" do
142
- it "succeeds" do
143
- first_res = client.get(server.endpoint)
144
- first_res.body.to_s
145
-
146
- second_res = client.get(server.endpoint)
147
-
148
- expect(first_res.body.to_s).to eq("<!doctype html>")
149
- expect(second_res.body.to_s).to eq("<!doctype html>")
150
- end
151
- end
152
-
153
- context "with a socket issue" do
154
- it "transparently reopens", :flaky do
155
- first_socket_id = client.get("#{server.endpoint}/socket").body.to_s
156
- expect(first_socket_id).to_not eq("")
157
- # Kill off the sockets we used
158
- # rubocop:disable Style/RescueModifier
159
- DummyServer::Servlet.sockets.each do |socket|
160
- socket.close rescue nil
161
- end
162
- DummyServer::Servlet.sockets.clear
163
- # rubocop:enable Style/RescueModifier
164
-
165
- # Should error because we tried to use a bad socket
166
- expect { client.get("#{server.endpoint}/socket").body.to_s }.to raise_error HTTP::ConnectionError
167
-
168
- # Should succeed since we create a new socket
169
- second_socket_id = client.get("#{server.endpoint}/socket").body.to_s
170
- expect(second_socket_id).to_not eq(first_socket_id)
171
- end
172
- end
173
-
174
- context "with a change in host" do
175
- it "errors" do
176
- expect { client.get("https://invalid.com/socket") }.to raise_error(/Persistence is enabled/i)
177
- end
178
- end
179
- end
180
-
181
- context "when disabled" do
182
- let(:options) { {} }
183
-
184
- it "opens new sockets", :flaky do
185
- expect(sockets_used).to_not include("")
186
- expect(sockets_used.uniq.length).to eq(2)
187
- end
188
- end
189
- end
190
- end
@@ -1,39 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "webrick/httpproxy"
4
-
5
- require "support/black_hole"
6
- require "support/servers/config"
7
- require "support/servers/runner"
8
-
9
- class ProxyServer < WEBrick::HTTPProxyServer
10
- include ServerConfig
11
-
12
- CONFIG = {
13
- :BindAddress => "127.0.0.1",
14
- :Port => 0,
15
- :AccessLog => BlackHole,
16
- :Logger => BlackHole,
17
- :RequestCallback => proc { |_, res| res["X-PROXIED"] = true }
18
- }.freeze
19
-
20
- def initialize
21
- super CONFIG
22
- end
23
- end
24
-
25
- class AuthProxyServer < WEBrick::HTTPProxyServer
26
- include ServerConfig
27
-
28
- AUTHENTICATOR = proc do |req, res|
29
- WEBrick::HTTPAuth.proxy_basic_auth(req, res, "proxy") do |user, pass|
30
- user == "username" && pass == "password"
31
- end
32
- end
33
-
34
- CONFIG = ProxyServer::CONFIG.merge :ProxyAuthProc => AUTHENTICATOR
35
-
36
- def initialize
37
- super CONFIG
38
- end
39
- end
@@ -1,11 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ServerConfig
4
- def addr
5
- config[:BindAddress]
6
- end
7
-
8
- def port
9
- config[:Port]
10
- end
11
- end
@@ -1,19 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ServerRunner
4
- def run_server(name)
5
- let! name do
6
- server = yield
7
-
8
- Thread.new { server.start }
9
-
10
- server
11
- end
12
-
13
- after do
14
- send(name).shutdown
15
- end
16
- end
17
- end
18
-
19
- RSpec.configure { |c| c.extend ServerRunner }
@@ -1,19 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "simplecov"
4
-
5
- if ENV["CI"]
6
- require "simplecov-lcov"
7
-
8
- SimpleCov::Formatter::LcovFormatter.config do |config|
9
- config.report_with_single_file = true
10
- config.lcov_file_name = "lcov.info"
11
- end
12
-
13
- SimpleCov.formatter = SimpleCov::Formatter::LcovFormatter
14
- end
15
-
16
- SimpleCov.start do
17
- add_filter "/spec/"
18
- minimum_coverage 80
19
- end
@@ -1,104 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "pathname"
4
-
5
- require "certificate_authority"
6
-
7
- module SSLHelper
8
- CERTS_PATH = Pathname.new File.expand_path("../../tmp/certs", __dir__)
9
-
10
- class RootCertificate < ::CertificateAuthority::Certificate
11
- EXTENSIONS = {"keyUsage" => {"usage" => %w[critical keyCertSign]}}.freeze
12
-
13
- def initialize
14
- super()
15
-
16
- subject.common_name = "honestachmed.com"
17
- serial_number.number = 1
18
- key_material.generate_key
19
-
20
- self.signing_entity = true
21
-
22
- sign!("extensions" => EXTENSIONS)
23
- end
24
-
25
- def file
26
- return @file if defined? @file
27
-
28
- CERTS_PATH.mkpath
29
-
30
- cert_file = CERTS_PATH.join("ca.crt")
31
- cert_file.open("w") { |io| io << to_pem }
32
-
33
- @file = cert_file.to_s
34
- end
35
- end
36
-
37
- class ChildCertificate < ::CertificateAuthority::Certificate
38
- def initialize(parent)
39
- super()
40
-
41
- subject.common_name = "127.0.0.1"
42
- serial_number.number = 1
43
-
44
- key_material.generate_key
45
-
46
- self.parent = parent
47
-
48
- sign!
49
- end
50
-
51
- def cert
52
- OpenSSL::X509::Certificate.new to_pem
53
- end
54
-
55
- def key
56
- OpenSSL::PKey::RSA.new key_material.private_key.to_pem
57
- end
58
- end
59
-
60
- class << self
61
- def server_context
62
- context = OpenSSL::SSL::SSLContext.new
63
-
64
- context.verify_mode = OpenSSL::SSL::VERIFY_PEER
65
- context.key = server_cert.key
66
- context.cert = server_cert.cert
67
- context.ca_file = ca.file
68
-
69
- context
70
- end
71
-
72
- def client_context
73
- context = OpenSSL::SSL::SSLContext.new
74
-
75
- context.options = OpenSSL::SSL::SSLContext::DEFAULT_PARAMS[:options]
76
- context.verify_mode = OpenSSL::SSL::VERIFY_PEER
77
- context.key = client_cert.key
78
- context.cert = client_cert.cert
79
- context.ca_file = ca.file
80
-
81
- context
82
- end
83
-
84
- def client_params
85
- {
86
- :key => client_cert.key,
87
- :cert => client_cert.cert,
88
- :ca_file => ca.file
89
- }
90
- end
91
-
92
- %w[server client].each do |side|
93
- class_eval <<-RUBY, __FILE__, __LINE__ + 1
94
- def #{side}_cert
95
- @#{side}_cert ||= ChildCertificate.new ca
96
- end
97
- RUBY
98
- end
99
-
100
- def ca
101
- @ca ||= RootCertificate.new
102
- end
103
- end
104
- end