logstash-output-http 5.2.5 → 5.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7bc2a004219fe6c466a5d60b24de18d1e70e8350da5f204279e43bdc0205b24a
4
- data.tar.gz: a3e44b45451030f4ba285df7875b418ef043df81e0689230b20a3de295484cde
3
+ metadata.gz: 6f8c174b5f5725b3dff206924edcff21ebc71899e386c1a301860dba438bbec5
4
+ data.tar.gz: dd6f158c15357a1dee6bfc3ad6e0faa4f6080c3fc2a89b6050b188bd3d016d4a
5
5
  SHA512:
6
- metadata.gz: d9d08edfc5f3cb590177d1b529b30fde4e7fc4ed3ee70bca99dcd2e0c4cdb01cb91f90d5deb0fb60efc6ce3e632ff7db2bcb82890c4f7ad6a08a576c209f9fd9
7
- data.tar.gz: 79c522bf0c7be7dd4d60abccef78eb52dd52f8f3a3cd30fd141941aef6e1288ea5e5249fe718fbf4452b2f81a8f09d168ffabba7ecc2a6b374a9f25cedf886a4
6
+ metadata.gz: 2d668381891939636b2462361fe0011d5ced8461b5a1a5e7f2662aa765e4672b6377e2dd37a05073eaa8e0602d60632496fa48ec9c42ab5063839f02214f2e9d
7
+ data.tar.gz: b3ff1de393aee131f18a1d8d75f05389f6a74642e695626b1e9b4b03eec99b7a26017cea50b97315f35594013650785a8b3e11bfcc7acd4e5d32ed118340f208
data/CHANGELOG.md CHANGED
@@ -1,3 +1,13 @@
1
+ ## 5.4.1
2
+ - Fix retry indefinitely in termination process. This feature requires Logstash 8.1 [#129](https://github.com/logstash-plugins/logstash-output-http/pull/129)
3
+ - Docs: Add retry policy description [#130](https://github.com/logstash-plugins/logstash-output-http/pull/130)
4
+
5
+ ## 5.4.0
6
+ - Introduce retryable unknown exceptions for "connection reset by peer" and "timeout" [#127](https://github.com/logstash-plugins/logstash-output-http/pull/127)
7
+
8
+ ## 5.3.0
9
+ - Feat: support ssl_verification_mode option [#126](https://github.com/logstash-plugins/logstash-output-http/pull/126)
10
+
1
11
  ## 5.2.5
2
12
  - Reduce amount of default logging on a failed request [#122](https://github.com/logstash-plugins/logstash-output-http/pull/122)
3
13
 
data/docs/index.asciidoc CHANGED
@@ -31,6 +31,40 @@ guaranteed!
31
31
 
32
32
  Beware, this gem does not yet support codecs. Please use the 'format' option for now.
33
33
 
34
+ [id="plugins-{type}s-{plugin}-retry_policy"]
35
+ ==== Retry policy
36
+
37
+ This output has two levels of retry: library and plugin.
38
+
39
+ [id="plugins-{type}s-{plugin}-library_retry"]
40
+ ===== Library retry
41
+
42
+ The library retry applies to IO related failures.
43
+ Non retriable errors include SSL related problems, unresolvable hosts,
44
+ connection issues, and OS/JVM level interruptions happening during a request.
45
+
46
+ The options for library retry are:
47
+
48
+ * <<plugins-{type}s-{plugin}-automatic_retries,`automatic_retries`>>.
49
+ Controls the number of times the plugin should retry after failures at the library level.
50
+ * <<plugins-{type}s-{plugin}-retry_non_idempotent,`retry_non_idempotent`>>.
51
+ When set to `false`, GET, HEAD, PUT, DELETE, OPTIONS, and TRACE requests will be
52
+ retried.
53
+
54
+ [id="plugins-{type}s-{plugin}-plugin_retry"]
55
+ ===== Plugin retry
56
+
57
+ The options for plugin level retry are:
58
+
59
+ * <<plugins-{type}s-{plugin}-retry_failed,`retry_failed`>>.
60
+ When set to `true`, the plugin retries indefinitely for HTTP error response codes defined
61
+ in the <<plugins-{type}s-{plugin}-retryable_codes,`retryable_codes`>> option
62
+ (429, 500, 502, 503, 504) and retryable exceptions (socket timeout/ error, DNS resolution failure and client protocol exception).
63
+ * <<plugins-{type}s-{plugin}-retryable_codes,`retryable_codes`>>.
64
+ Sets http response codes that trigger a retry.
65
+
66
+ NOTE: The `retry_failed` option does not control the library level retry.
67
+
34
68
  [id="plugins-{type}s-{plugin}-options"]
35
69
  ==== Http Output Configuration Options
36
70
 
@@ -66,6 +100,7 @@ This plugin supports the following configuration options plus the <<plugins-{typ
66
100
  | <<plugins-{type}s-{plugin}-retry_non_idempotent>> |<<boolean,boolean>>|No
67
101
  | <<plugins-{type}s-{plugin}-retryable_codes>> |<<number,number>>|No
68
102
  | <<plugins-{type}s-{plugin}-socket_timeout>> |<<number,number>>|No
103
+ | <<plugins-{type}s-{plugin}-ssl_verification_mode>> |<<string,string>>|No
69
104
  | <<plugins-{type}s-{plugin}-truststore>> |a valid filesystem path|No
70
105
  | <<plugins-{type}s-{plugin}-truststore_password>> |<<password,password>>|No
71
106
  | <<plugins-{type}s-{plugin}-truststore_type>> |<<string,string>>|No
@@ -84,12 +119,10 @@ output plugins.
84
119
  * Value type is <<number,number>>
85
120
  * Default value is `1`
86
121
 
87
- How many times should the client retry a failing URL. We highly recommend NOT setting this value
88
- to zero if keepalive is enabled. Some servers incorrectly end keepalives early requiring a retry!
89
- Only IO related failures will be retried, such as connection timeouts and unreachable hosts.
90
- Valid but non 2xx HTTP responses will always be retried, regardless of the value of this setting,
91
- unless `retry_failed` is set.
92
- Note: if `retry_non_idempotent` is NOT set only GET, HEAD, PUT, DELETE, OPTIONS, and TRACE requests will be retried.
122
+ How many times should the client retry a failing URL. We recommend setting this option
123
+ to a value other than zero if the <<plugins-{type}s-{plugin}-keepalive,`keepalive` option>> is enabled.
124
+ Some servers incorrectly end keepalives early, requiring a retry.
125
+ See <<plugins-{type}s-{plugin}-retry_policy,Retry Policy>> for more information.
93
126
 
94
127
  [id="plugins-{type}s-{plugin}-cacert"]
95
128
  ===== `cacert`
@@ -310,7 +343,12 @@ Timeout (in seconds) for the entire request
310
343
  * Value type is <<boolean,boolean>>
311
344
  * Default value is `true`
312
345
 
313
- Set this to false if you don't want this output to retry failed requests
346
+ Note that this option controls plugin-level retries only.
347
+ It has no affect on library-level retries.
348
+
349
+ Set this option to `false` if you want to disable infinite retries for HTTP error response codes defined in the <<plugins-{type}s-{plugin}-retryable_codes,`retryable_codes`>> or
350
+ retryable exceptions (Timeout, SocketException, ClientProtocolException, ResolutionFailure and SocketTimeout).
351
+ See <<plugins-{type}s-{plugin}-retry_policy,Retry policy>> for more information.
314
352
 
315
353
  [id="plugins-{type}s-{plugin}-retry_non_idempotent"]
316
354
  ===== `retry_non_idempotent`
@@ -318,8 +356,10 @@ Set this to false if you don't want this output to retry failed requests
318
356
  * Value type is <<boolean,boolean>>
319
357
  * Default value is `false`
320
358
 
321
- If `automatic_retries` is enabled this will cause non-idempotent HTTP verbs (such as POST) to be retried.
322
- This only affects connectivity related errors (see related `automatic_retries` setting).
359
+ When this option is set to `false` and `automatic_retries` is enabled, GET, HEAD, PUT, DELETE, OPTIONS, and TRACE requests will be retried.
360
+
361
+ When set to `true` and `automatic_retries` is enabled, this will cause non-idempotent HTTP verbs (such as POST) to be retried.
362
+ See <<plugins-{type}s-{plugin}-retry_policy,Retry Policy>> for more information.
323
363
 
324
364
  [id="plugins-{type}s-{plugin}-retryable_codes"]
325
365
  ===== `retryable_codes`
@@ -327,7 +367,8 @@ This only affects connectivity related errors (see related `automatic_retries` s
327
367
  * Value type is <<number,number>>
328
368
  * Default value is `[429, 500, 502, 503, 504]`
329
369
 
330
- If encountered as response codes this plugin will retry these requests
370
+ If the plugin encounters these response codes, the plugin will retry indefinitely.
371
+ See <<plugins-{type}s-{plugin}-retry_policy,Retry Policy>> for more information.
331
372
 
332
373
  [id="plugins-{type}s-{plugin}-socket_timeout"]
333
374
  ===== `socket_timeout`
@@ -337,6 +378,22 @@ If encountered as response codes this plugin will retry these requests
337
378
 
338
379
  Timeout (in seconds) to wait for data on the socket. Default is `10s`
339
380
 
381
+ [id="plugins-{type}s-{plugin}-ssl_verification_mode"]
382
+ ===== `ssl_verification_mode`
383
+
384
+ * Value type is <<string,string>>
385
+ * Supported values are: `full`, `none`
386
+ * Default value is `full`
387
+
388
+ Controls the verification of server certificates.
389
+ The `full` option verifies that the provided certificate is signed by a trusted authority (CA)
390
+ and also that the server’s hostname (or IP address) matches the names identified within the certificate.
391
+
392
+ The `none` setting performs no verification of the server’s certificate.
393
+ This mode disables many of the security benefits of SSL/TLS and should only be used after cautious consideration.
394
+ It is primarily intended as a temporary diagnostic mechanism when attempting to resolve TLS errors.
395
+ Using `none` in production environments is strongly discouraged.
396
+
340
397
  [id="plugins-{type}s-{plugin}-truststore"]
341
398
  ===== `truststore`
342
399
 
@@ -388,4 +445,4 @@ See https://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache
388
445
  [id="plugins-{type}s-{plugin}-common-options"]
389
446
  include::{include_path}/{type}.asciidoc[]
390
447
 
391
- :default_codec!:
448
+ :default_codec!:
@@ -23,6 +23,13 @@ class LogStash::Outputs::Http < LogStash::Outputs::Base
23
23
  ::Manticore::SocketTimeout
24
24
  ]
25
25
 
26
+ RETRYABLE_UNKNOWN_EXCEPTION_STRINGS = [
27
+ /Connection reset by peer/i,
28
+ /Read Timed out/i
29
+ ]
30
+
31
+ class PluginInternalQueueLeftoverError < StandardError; end
32
+
26
33
  # This output lets you send events to a
27
34
  # generic HTTP(S) endpoint
28
35
  #
@@ -138,10 +145,11 @@ class LogStash::Outputs::Http < LogStash::Outputs::Base
138
145
  end
139
146
 
140
147
  def log_retryable_response(response)
148
+ retry_msg = @retry_failed ? 'will retry' : "won't retry"
141
149
  if (response.code == 429)
142
- @logger.debug? && @logger.debug("Encountered a 429 response, will retry. This is not serious, just flow control via HTTP")
150
+ @logger.debug? && @logger.debug("Encountered a 429 response, #{retry_msg}. This is not serious, just flow control via HTTP")
143
151
  else
144
- @logger.warn("Encountered a retryable HTTP request in HTTP output, will retry", :code => response.code, :body => response.body)
152
+ @logger.warn("Encountered a retryable HTTP request in HTTP output, #{retry_msg}", :code => response.code, :body => response.body)
145
153
  end
146
154
  end
147
155
 
@@ -172,6 +180,9 @@ class LogStash::Outputs::Http < LogStash::Outputs::Base
172
180
 
173
181
  event, attempt = popped
174
182
 
183
+ raise PluginInternalQueueLeftoverError.new("Received pipeline shutdown request but http output has unfinished events. " \
184
+ "If persistent queue is enabled, events will be retried.") if attempt > 2 && pipeline_shutdown_requested?
185
+
175
186
  action, event, attempt = send_event(event, attempt)
176
187
  begin
177
188
  action = :failure if action == :retry && !@retry_failed
@@ -216,6 +227,11 @@ class LogStash::Outputs::Http < LogStash::Outputs::Base
216
227
  raise e
217
228
  end
218
229
 
230
+ def pipeline_shutdown_requested?
231
+ return super if defined?(super) # since LS 8.1.0
232
+ nil
233
+ end
234
+
219
235
  def sleep_for_attempt(attempt)
220
236
  sleep_for = attempt**2
221
237
  sleep_for = sleep_for <= 60 ? sleep_for : 60
@@ -294,12 +310,21 @@ class LogStash::Outputs::Http < LogStash::Outputs::Base
294
310
  end
295
311
 
296
312
  def retryable_exception?(exception)
297
- RETRYABLE_MANTICORE_EXCEPTIONS.any? {|me| exception.is_a?(me) }
313
+ retryable_manticore_exception?(exception) || retryable_unknown_exception?(exception)
314
+ end
315
+
316
+ def retryable_manticore_exception?(exception)
317
+ RETRYABLE_MANTICORE_EXCEPTIONS.any? {|me| exception.is_a?(me)}
318
+ end
319
+
320
+ def retryable_unknown_exception?(exception)
321
+ exception.is_a?(::Manticore::UnknownException) &&
322
+ RETRYABLE_UNKNOWN_EXCEPTION_STRINGS.any? { |snippet| exception.message =~ snippet }
298
323
  end
299
324
 
300
325
  # This is split into a separate method mostly to help testing
301
326
  def log_failure(message, opts)
302
- @logger.error("[HTTP Output Failure] #{message}", opts)
327
+ @logger.error(message, opts)
303
328
  end
304
329
 
305
330
  # Format the HTTP body
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'logstash-output-http'
3
- s.version = '5.2.5'
3
+ s.version = '5.4.1'
4
4
  s.licenses = ['Apache License (2.0)']
5
5
  s.summary = "Sends events to a generic HTTP or HTTPS endpoint"
6
6
  s.description = "This gem is a Logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/logstash-plugin install gemname. This gem is not a stand-alone program"
@@ -20,7 +20,7 @@ Gem::Specification.new do |s|
20
20
 
21
21
  # Gem dependencies
22
22
  s.add_runtime_dependency "logstash-core-plugin-api", ">= 1.60", "<= 2.99"
23
- s.add_runtime_dependency "logstash-mixin-http_client", ">= 6.0.0", "< 8.0.0"
23
+ s.add_runtime_dependency "logstash-mixin-http_client", ">= 7.1.0", "< 8.0.0"
24
24
 
25
25
  s.add_development_dependency 'logstash-devutils'
26
26
  s.add_development_dependency 'sinatra'
@@ -3,6 +3,9 @@ require "logstash/outputs/http"
3
3
  require "logstash/codecs/plain"
4
4
  require "thread"
5
5
  require "sinatra"
6
+ require "webrick"
7
+ require "webrick/https"
8
+ require 'openssl'
6
9
  require_relative "../supports/compressed_requests"
7
10
 
8
11
  PORT = rand(65535-1024) + 1025
@@ -22,9 +25,20 @@ class TestApp < Sinatra::Base
22
25
  # on the fly uncompress gzip content
23
26
  use CompressedRequests
24
27
 
25
- # disable WEBrick logging
28
+ set :environment, :production
29
+ set :sessions, false
30
+
31
+ @@server_settings = {
32
+ :AccessLog => [], # disable WEBrick logging
33
+ :Logger => WEBrick::BasicLog::new(nil, WEBrick::BasicLog::FATAL)
34
+ }
35
+
26
36
  def self.server_settings
27
- { :AccessLog => [], :Logger => WEBrick::BasicLog::new(nil, WEBrick::BasicLog::FATAL) }
37
+ @@server_settings
38
+ end
39
+
40
+ def self.server_settings=(settings)
41
+ @@server_settings = settings
28
42
  end
29
43
 
30
44
  def self.multiroute(methods, path, &block)
@@ -72,31 +86,22 @@ class TestApp < Sinatra::Base
72
86
  end
73
87
  end
74
88
 
75
- RSpec.configure do |config|
89
+ RSpec.configure do
76
90
  #http://stackoverflow.com/questions/6557079/start-and-call-ruby-http-server-in-the-same-script
77
- def sinatra_run_wait(app, opts)
91
+ def start_app_and_wait(app, opts = {})
78
92
  queue = Queue.new
79
93
 
80
- t = java.lang.Thread.new(
81
- proc do
82
- begin
83
- app.run!(opts) do |server|
84
- queue.push("started")
85
- end
86
- rescue => e
87
- puts "Error in webserver thread #{e}"
88
- # ignore
94
+ Thread.start do
95
+ begin
96
+ app.start!({ server: 'WEBrick', port: PORT }.merge opts) do |server|
97
+ queue.push(server)
89
98
  end
99
+ rescue => e
100
+ warn "Error starting app: #{e.inspect}" # ignore
90
101
  end
91
- )
92
- t.daemon = true
93
- t.start
94
- queue.pop # blocks until the run! callback runs
95
- end
102
+ end
96
103
 
97
- config.before(:suite) do
98
- sinatra_run_wait(TestApp, :port => PORT, :server => 'webrick')
99
- puts "Test webserver on port #{PORT}"
104
+ queue.pop # blocks until the start! callback runs
100
105
  end
101
106
  end
102
107
 
@@ -104,6 +109,15 @@ describe LogStash::Outputs::Http do
104
109
  # Wait for the async request to finish in this spinlock
105
110
  # Requires pool_max to be 1
106
111
 
112
+ before(:all) do
113
+ @server = start_app_and_wait(TestApp)
114
+ end
115
+
116
+ after(:all) do
117
+ @server.shutdown # WEBrick::HTTPServer
118
+ TestApp.stop! rescue nil
119
+ end
120
+
107
121
  let(:port) { PORT }
108
122
  let(:event) {
109
123
  LogStash::Event.new({"message" => "hi"})
@@ -112,6 +126,44 @@ describe LogStash::Outputs::Http do
112
126
  let(:method) { "post" }
113
127
 
114
128
  shared_examples("verb behavior") do |method|
129
+
130
+ shared_examples("failure log behaviour") do
131
+ it "logs failure" do
132
+ expect(subject).to have_received(:log_failure).with(any_args)
133
+ end
134
+
135
+ it "does not log headers" do
136
+ expect(subject).to have_received(:log_failure).with(anything, hash_not_including(:headers))
137
+ end
138
+
139
+ it "does not log the message body" do
140
+ expect(subject).to have_received(:log_failure).with(anything, hash_not_including(:body))
141
+ end
142
+
143
+ context "with debug log level" do
144
+ before :all do
145
+ @current_log_level = LogStash::Logging::Logger.get_logging_context.get_root_logger.get_level.to_s.downcase
146
+ LogStash::Logging::Logger.configure_logging "debug"
147
+ end
148
+ after :all do
149
+ LogStash::Logging::Logger.configure_logging @current_log_level
150
+ end
151
+
152
+ it "logs a failure" do
153
+ expect(subject).to have_received(:log_failure).with(any_args)
154
+ end
155
+
156
+ it "logs headers" do
157
+ expect(subject).to have_received(:log_failure).with(anything, hash_including(:headers))
158
+ end
159
+
160
+ it "logs the body" do
161
+ expect(subject).to have_received(:log_failure).with(anything, hash_including(:body))
162
+ end
163
+ end
164
+
165
+ end
166
+
115
167
  let(:verb_behavior_config) { {"url" => url, "http_method" => method, "pool_max" => 1} }
116
168
  subject { LogStash::Outputs::Http.new(verb_behavior_config) }
117
169
 
@@ -199,44 +251,96 @@ describe LogStash::Outputs::Http do
199
251
  end
200
252
  end
201
253
 
202
- context "on exception" do
254
+ context "on retryable unknown exception" do
203
255
  before :each do
204
- allow(subject.client).to receive(:send).and_raise RuntimeError
256
+ raised = false
257
+ original_method = subject.client.method(:send)
258
+ allow(subject).to receive(:send_event).and_call_original
259
+ expect(subject.client).to receive(:send) do |*args|
260
+ unless raised
261
+ raised = true
262
+ raise ::Manticore::UnknownException.new("Read timed out")
263
+ end
264
+ original_method.call(args)
265
+ end
205
266
  subject.multi_receive([event])
206
267
  end
207
268
 
208
- it "should not log headers" do
209
- expect(subject).to have_received(:log_failure).with(anything, hash_not_including(:headers))
210
- end
269
+ include_examples("failure log behaviour")
211
270
 
212
- it "should not log the body" do
213
- expect(subject).to have_received(:log_failure).with(anything, hash_not_including(:body))
271
+ it "retries" do
272
+ expect(subject).to have_received(:send_event).exactly(2).times
214
273
  end
274
+ end
215
275
 
216
- context "with debug log level" do
217
- before :all do
218
- @current_log_level = LogStash::Logging::Logger.get_logging_context.get_root_logger.get_level.to_s.downcase
219
- LogStash::Logging::Logger.configure_logging "debug"
220
- end
221
- after :all do
222
- LogStash::Logging::Logger.configure_logging @current_log_level
276
+ context "on non-retryable unknown exception" do
277
+ before :each do
278
+ raised = false
279
+ original_method = subject.client.method(:send)
280
+ allow(subject).to receive(:send_event).and_call_original
281
+ expect(subject.client).to receive(:send) do |*args|
282
+ unless raised
283
+ raised = true
284
+ raise ::Manticore::UnknownException.new("broken")
285
+ end
286
+ original_method.call(args)
223
287
  end
288
+ subject.multi_receive([event])
289
+ end
224
290
 
225
- it "should log a failure" do
226
- expect(subject).to have_received(:log_failure).with(any_args)
227
- end
291
+ include_examples("failure log behaviour")
228
292
 
229
- it "should not log headers" do
230
- expect(subject).to have_received(:log_failure).with(anything, hash_including(:headers))
293
+ it "does not retry" do
294
+ expect(subject).to have_received(:send_event).exactly(1).times
295
+ end
296
+ end
297
+
298
+ context "on non-retryable exception" do
299
+ before :each do
300
+ raised = false
301
+ original_method = subject.client.method(:send)
302
+ allow(subject).to receive(:send_event).and_call_original
303
+ expect(subject.client).to receive(:send) do |*args|
304
+ unless raised
305
+ raised = true
306
+ raise RuntimeError.new("broken")
307
+ end
308
+ original_method.call(args)
231
309
  end
310
+ subject.multi_receive([event])
311
+ end
232
312
 
233
- it "should not log the body" do
234
- expect(subject).to have_received(:log_failure).with(anything, hash_including(:body))
313
+ include_examples("failure log behaviour")
314
+
315
+ it "does not retry" do
316
+ expect(subject).to have_received(:send_event).exactly(1).times
317
+ end
318
+ end
319
+
320
+ context "on retryable exception" do
321
+ before :each do
322
+ raised = false
323
+ original_method = subject.client.method(:send)
324
+ allow(subject).to receive(:send_event).and_call_original
325
+ expect(subject.client).to receive(:send) do |*args|
326
+ unless raised
327
+ raised = true
328
+ raise ::Manticore::Timeout.new("broken")
329
+ end
330
+ original_method.call(args)
235
331
  end
332
+ subject.multi_receive([event])
236
333
  end
334
+
335
+ it "retries" do
336
+ expect(subject).to have_received(:send_event).exactly(2).times
337
+ end
338
+
339
+ include_examples("failure log behaviour")
237
340
  end
238
341
  end
239
342
 
343
+
240
344
  LogStash::Outputs::Http::VALID_METHODS.each do |method|
241
345
  context "when using '#{method}'" do
242
346
  include_examples("verb behavior", method)
@@ -397,4 +501,93 @@ describe LogStash::Outputs::Http do
397
501
  let(:base_config) { { "http_compression" => true } }
398
502
  end
399
503
  end
504
+
505
+ describe "retryable error in termination" do
506
+ let(:url) { "http://localhost:#{port-1}/invalid" }
507
+ let(:events) { [event] }
508
+ let(:config) { {"url" => url, "http_method" => "get", "pool_max" => 1} }
509
+
510
+ subject { LogStash::Outputs::Http.new(config) }
511
+
512
+ before do
513
+ subject.register
514
+ allow(subject).to receive(:pipeline_shutdown_requested?).and_return(true)
515
+ end
516
+
517
+ it "raise exception to exit indefinitely retry" do
518
+ expect { subject.multi_receive(events) }.to raise_error(LogStash::Outputs::Http::PluginInternalQueueLeftoverError)
519
+ end
520
+ end
521
+ end
522
+
523
+ describe LogStash::Outputs::Http do # different block as we're starting web server with TLS
524
+
525
+ @@default_server_settings = TestApp.server_settings.dup
526
+
527
+ before do
528
+ cert, key = WEBrick::Utils.create_self_signed_cert 2048, [["CN", ssl_cert_host]], "Logstash testing"
529
+ TestApp.server_settings = @@default_server_settings.merge({
530
+ :SSLEnable => true,
531
+ :SSLVerifyClient => OpenSSL::SSL::VERIFY_NONE,
532
+ :SSLCertificate => cert,
533
+ :SSLPrivateKey => key
534
+ })
535
+
536
+ TestApp.last_request = nil
537
+
538
+ @server = start_app_and_wait(TestApp)
539
+ end
540
+
541
+ after do
542
+ @server.shutdown # WEBrick::HTTPServer
543
+
544
+ TestApp.stop! rescue nil
545
+ TestApp.server_settings = @@default_server_settings
546
+ end
547
+
548
+ let(:ssl_cert_host) { 'localhost' }
549
+
550
+ let(:port) { PORT }
551
+ let(:url) { "https://localhost:#{port}/good" }
552
+ let(:method) { "post" }
553
+
554
+ let(:config) { { "url" => url, "http_method" => method } }
555
+
556
+ subject { LogStash::Outputs::Http.new(config) }
557
+
558
+ before { subject.register }
559
+ after { subject.close }
560
+
561
+ let(:last_request) { TestApp.last_request }
562
+ let(:last_request_body) { last_request.body.read }
563
+
564
+ let(:event) { LogStash::Event.new("message" => "hello!") }
565
+
566
+ context 'with default (full) verification' do
567
+
568
+ let(:config) { super() } # 'ssl_verification_mode' => 'full'
569
+
570
+ it "does NOT process the request (due client protocol exception)" do
571
+ # Manticore's default verification does not accept self-signed certificates!
572
+ Thread.start do
573
+ subject.multi_receive [ event ]
574
+ end
575
+ sleep 1.5
576
+
577
+ expect(last_request).to be nil
578
+ end
579
+
580
+ end
581
+
582
+ context 'with verification disabled' do
583
+
584
+ let(:config) { super().merge 'ssl_verification_mode' => 'none' }
585
+
586
+ it "should process the request" do
587
+ subject.multi_receive [ event ]
588
+ expect(last_request_body).to include '"message":"hello!"'
589
+ end
590
+
591
+ end
592
+
400
593
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logstash-output-http
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.2.5
4
+ version: 5.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Elastic
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-05-27 00:00:00.000000000 Z
11
+ date: 2022-03-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement
@@ -35,7 +35,7 @@ dependencies:
35
35
  requirements:
36
36
  - - ">="
37
37
  - !ruby/object:Gem::Version
38
- version: 6.0.0
38
+ version: 7.1.0
39
39
  - - "<"
40
40
  - !ruby/object:Gem::Version
41
41
  version: 8.0.0
@@ -46,7 +46,7 @@ dependencies:
46
46
  requirements:
47
47
  - - ">="
48
48
  - !ruby/object:Gem::Version
49
- version: 6.0.0
49
+ version: 7.1.0
50
50
  - - "<"
51
51
  - !ruby/object:Gem::Version
52
52
  version: 8.0.0
@@ -132,8 +132,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
132
132
  - !ruby/object:Gem::Version
133
133
  version: '0'
134
134
  requirements: []
135
- rubyforge_project:
136
- rubygems_version: 2.6.13
135
+ rubygems_version: 3.1.6
137
136
  signing_key:
138
137
  specification_version: 4
139
138
  summary: Sends events to a generic HTTP or HTTPS endpoint