logstash-output-http 5.0.1 → 5.1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ddd34eaab5f5f023138eede5762b6911c6542be9
4
- data.tar.gz: ab1aec99d160c6dcd84fe624d5d4274fa0840dfd
3
+ metadata.gz: ed1975dd9a23d8a355ca14ccd0d191d387620356
4
+ data.tar.gz: d4ce66fe7f7c0b4e5396f819a70aeb62292be625
5
5
  SHA512:
6
- metadata.gz: 2e5d6443d21b3caf9172a53c6469a4ba9cd8351f3c62e10ecc2b905eabf2710427b63938d0b56e66245487e59486c6dac05e1d1a5a5825c2692914bd0a8b4892
7
- data.tar.gz: 6ae047e197b2e1ff442ef460d49e22f40b5746c0cde155d2752778d23836fe9fae4a69712c38377d5a3780b94fbb52ce70aeea96b7ec66babb6b1bbec4f0da6b
6
+ metadata.gz: d393ce2604784a67dcdedd1196650054cc32e246e16fb13fc93638941fbf6f0dffad804a758b9b99bd87ebefa16ed194b3e5558c52bf92b403c54af1fc72cd70
7
+ data.tar.gz: 70237b74bcdbeaeb2a0bd482f07189faf3c3f9dedda59226ca29086f9967eb7cf93dab8caecfb10e47093b508ca9aa8d2fc5013fec3f3b84feadca79dec6cabb
@@ -1,3 +1,6 @@
1
+ ## 5.1.0
2
+ - Adding a new option `http_compression` for sending compressed payload with the `Content-Encoding: gzip` header to the configured http endpoint #66
3
+
1
4
  ## 5.0.1
2
5
  - Fix some documentation issues
3
6
 
@@ -48,6 +48,7 @@ This plugin supports the following configuration options plus the <<plugins-{typ
48
48
  | <<plugins-{type}s-{plugin}-follow_redirects>> |<<boolean,boolean>>|No
49
49
  | <<plugins-{type}s-{plugin}-format>> |<<string,string>>, one of `["json", "form", "message"]`|No
50
50
  | <<plugins-{type}s-{plugin}-headers>> |<<hash,hash>>|No
51
+ | <<plugins-{type}s-{plugin}-http_compression>> |<<boolean,boolean>>|No
51
52
  | <<plugins-{type}s-{plugin}-http_method>> |<<string,string>>, one of `["put", "post", "patch", "delete", "get", "head"]`|Yes
52
53
  | <<plugins-{type}s-{plugin}-ignorable_codes>> |<<number,number>>|No
53
54
  | <<plugins-{type}s-{plugin}-keepalive>> |<<boolean,boolean>>|No
@@ -172,6 +173,15 @@ Otherwise, the event is sent as json.
172
173
  Custom headers to use
173
174
  format is `headers => ["X-My-Header", "%{host}"]`
174
175
 
176
+ [id="plugins-{type}s-{plugin}-http_compression"]
177
+ ===== `http_compression`
178
+
179
+ * Value type is <<boolean,boolean>>
180
+ * Default value is `false`
181
+
182
+ Enable request compression support. With this enabled the plugin will compress
183
+ http requests using gzip.
184
+
175
185
  [id="plugins-{type}s-{plugin}-http_method"]
176
186
  ===== `http_method`
177
187
 
@@ -4,6 +4,7 @@ require "logstash/namespace"
4
4
  require "logstash/json"
5
5
  require "uri"
6
6
  require "logstash/plugin_mixins/http_client"
7
+ require "zlib"
7
8
 
8
9
  class LogStash::Outputs::Http < LogStash::Outputs::Base
9
10
  include LogStash::PluginMixins::HttpClient
@@ -80,6 +81,9 @@ class LogStash::Outputs::Http < LogStash::Outputs::Base
80
81
  # Otherwise, the event is sent as json.
81
82
  config :format, :validate => ["json", "form", "message"], :default => "json"
82
83
 
84
+ # Set this to true if you want to enable gzip compression for your http requests
85
+ config :http_compression, :validate => :boolean, :default => false
86
+
83
87
  config :message, :validate => :string
84
88
 
85
89
  def register
@@ -196,6 +200,12 @@ class LogStash::Outputs::Http < LogStash::Outputs::Base
196
200
  url = event.sprintf(@url)
197
201
  headers = event_headers(event)
198
202
 
203
+ # Compress the body and add appropriate header
204
+ if @http_compression == true
205
+ headers["Content-Encoding"] = "gzip"
206
+ body = gzip(body)
207
+ end
208
+
199
209
  # Create an async request
200
210
  request = client.background.send(@http_method, url, :body => body, :headers => headers)
201
211
 
@@ -300,6 +310,16 @@ class LogStash::Outputs::Http < LogStash::Outputs::Base
300
310
  end
301
311
  end
302
312
 
313
+ # gzip data
314
+ def gzip(data)
315
+ gz = StringIO.new
316
+ gz.set_encoding("BINARY")
317
+ z = Zlib::GzipWriter.new(gz)
318
+ z.write(data)
319
+ z.close
320
+ gz.string
321
+ end
322
+
303
323
  def convert_mapping(mapping, event)
304
324
  if mapping.is_a?(Hash)
305
325
  mapping.reduce({}) do |acc, kv|
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'logstash-output-http'
3
- s.version = '5.0.1'
3
+ s.version = '5.1.0'
4
4
  s.licenses = ['Apache License (2.0)']
5
5
  s.summary = "This output lets you `PUT` or `POST` events to a generic HTTP(S) 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"
@@ -3,6 +3,7 @@ require "logstash/outputs/http"
3
3
  require "logstash/codecs/plain"
4
4
  require "thread"
5
5
  require "sinatra"
6
+ require_relative "../supports/compressed_requests"
6
7
 
7
8
  PORT = rand(65535-1024) + 1025
8
9
 
@@ -16,8 +17,10 @@ end
16
17
  #
17
18
  # == Sinatra (v1.4.6) has taken the stage on 51572 for development with backup from WEBrick
18
19
  # == Sinatra has ended his set (crowd applauds)
19
-
20
+ #
20
21
  class TestApp < Sinatra::Base
22
+ # on the fly uncompress gzip content
23
+ use CompressedRequests
21
24
 
22
25
  # disable WEBrick logging
23
26
  def self.server_settings
@@ -38,11 +41,11 @@ class TestApp < Sinatra::Base
38
41
  def self.last_request
39
42
  @last_request
40
43
  end
41
-
44
+
42
45
  def self.retry_fail_count=(count)
43
46
  @retry_fail_count = count
44
47
  end
45
-
48
+
46
49
  def self.retry_fail_count()
47
50
  @retry_fail_count
48
51
  end
@@ -56,10 +59,10 @@ class TestApp < Sinatra::Base
56
59
  self.class.last_request = request
57
60
  [400, "YUP"]
58
61
  end
59
-
62
+
60
63
  multiroute(%w(get post put patch delete), "/retry") do
61
64
  self.class.last_request = request
62
-
65
+
63
66
  if self.class.retry_fail_count > 0
64
67
  self.class.retry_fail_count -= 1
65
68
  [429, "Will succeed in #{self.class.retry_fail_count}"]
@@ -80,7 +83,7 @@ RSpec.configure do |config|
80
83
  app.run!(opts) do |server|
81
84
  queue.push("started")
82
85
  end
83
- rescue => e
86
+ rescue => e
84
87
  puts "Error in webserver thread #{e}"
85
88
  # ignore
86
89
  end
@@ -158,7 +161,7 @@ describe LogStash::Outputs::Http do
158
161
  expect(subject).to have_received(:log_failure).with(any_args)
159
162
  end
160
163
  end
161
-
164
+
162
165
  context "with ignorable failing requests" do
163
166
  let(:url) { "http://localhost:#{port}/bad"}
164
167
  let(:verb_behavior_config) { super.merge("ignorable_codes" => [400]) }
@@ -171,7 +174,7 @@ describe LogStash::Outputs::Http do
171
174
  expect(subject).not_to have_received(:log_failure).with(any_args)
172
175
  end
173
176
  end
174
-
177
+
175
178
  context "with retryable failing requests" do
176
179
  let(:url) { "http://localhost:#{port}/retry"}
177
180
 
@@ -184,12 +187,12 @@ describe LogStash::Outputs::Http do
184
187
  it "should log a failure 2 times" do
185
188
  expect(subject).to have_received(:log_failure).with(any_args).twice
186
189
  end
187
-
190
+
188
191
  it "should make three total requests" do
189
192
  expect(subject).to have_received(:send_event).exactly(3).times
190
193
  end
191
- end
192
-
194
+ end
195
+
193
196
  end
194
197
  end
195
198
 
@@ -225,7 +228,8 @@ describe LogStash::Outputs::Http do
225
228
  end
226
229
  end
227
230
 
228
- describe "integration tests" do
231
+ shared_examples "integration tests" do
232
+ let(:base_config) { {} }
229
233
  let(:url) { "http://localhost:#{port}/good" }
230
234
  let(:event) {
231
235
  LogStash::Event.new("foo" => "bar", "baz" => "bot", "user" => "McBest")
@@ -239,7 +243,7 @@ describe LogStash::Outputs::Http do
239
243
 
240
244
  describe "sending with the default (JSON) config" do
241
245
  let(:config) {
242
- {"url" => url, "http_method" => "post", "pool_max" => 1}
246
+ base_config.merge({"url" => url, "http_method" => "post", "pool_max" => 1})
243
247
  }
244
248
  let(:expected_body) { LogStash::Json.dump(event) }
245
249
  let(:expected_content_type) { "application/json" }
@@ -249,7 +253,7 @@ describe LogStash::Outputs::Http do
249
253
 
250
254
  describe "sending the event as a form" do
251
255
  let(:config) {
252
- {"url" => url, "http_method" => "post", "pool_max" => 1, "format" => "form"}
256
+ base_config.merge({"url" => url, "http_method" => "post", "pool_max" => 1, "format" => "form"})
253
257
  }
254
258
  let(:expected_body) { subject.send(:encode, event.to_hash) }
255
259
  let(:expected_content_type) { "application/x-www-form-urlencoded" }
@@ -259,7 +263,7 @@ describe LogStash::Outputs::Http do
259
263
 
260
264
  describe "sending the event as a message" do
261
265
  let(:config) {
262
- {"url" => url, "http_method" => "post", "pool_max" => 1, "format" => "message", "message" => "%{foo} AND %{baz}"}
266
+ base_config.merge({"url" => url, "http_method" => "post", "pool_max" => 1, "format" => "message", "message" => "%{foo} AND %{baz}"})
263
267
  }
264
268
  let(:expected_body) { "#{event.get("foo")} AND #{event.get("baz")}" }
265
269
  let(:expected_content_type) { "text/plain" }
@@ -269,7 +273,7 @@ describe LogStash::Outputs::Http do
269
273
 
270
274
  describe "sending a mapped event" do
271
275
  let(:config) {
272
- {"url" => url, "http_method" => "post", "pool_max" => 1, "mapping" => {"blah" => "X %{foo}"} }
276
+ base_config.merge({"url" => url, "http_method" => "post", "pool_max" => 1, "mapping" => {"blah" => "X %{foo}"} })
273
277
  }
274
278
  let(:expected_body) { LogStash::Json.dump("blah" => "X #{event.get("foo")}") }
275
279
  let(:expected_content_type) { "application/json" }
@@ -279,7 +283,7 @@ describe LogStash::Outputs::Http do
279
283
 
280
284
  describe "sending a mapped, nested event" do
281
285
  let(:config) {
282
- {
286
+ base_config.merge({
283
287
  "url" => url,
284
288
  "http_method" => "post",
285
289
  "pool_max" => 1,
@@ -292,7 +296,7 @@ describe LogStash::Outputs::Http do
292
296
  "user" => "Z %{user}"
293
297
  }]
294
298
  }
295
- }
299
+ })
296
300
  }
297
301
  let(:expected_body) {
298
302
  LogStash::Json.dump({
@@ -310,4 +314,14 @@ describe LogStash::Outputs::Http do
310
314
  include_examples("a received event")
311
315
  end
312
316
  end
317
+
318
+ describe "integration test without gzip compression" do
319
+ include_examples("integration tests")
320
+ end
321
+
322
+ describe "integration test with gzip compression" do
323
+ include_examples("integration tests") do
324
+ let(:base_config) { { "http_compression" => true } }
325
+ end
326
+ end
313
327
  end
@@ -0,0 +1,38 @@
1
+ # encoding: utf-8
2
+ #
3
+ # based on relistan's rack handler
4
+ # out of the box rack only gives use the rack deflater handler to return compressed
5
+ # response, this gist offer the inverse and should work on all rack based app like sinatra or rails.
6
+ #
7
+ # original source: https://gist.github.com/relistan/2109707
8
+ require "zlib"
9
+
10
+ class CompressedRequests
11
+ def initialize(app)
12
+ @app = app
13
+ end
14
+
15
+ def encoding_handled?(env)
16
+ ['gzip', 'deflate'].include? env['HTTP_CONTENT_ENCODING']
17
+ end
18
+
19
+ def call(env)
20
+ if encoding_handled?(env)
21
+ extracted = decode(env['rack.input'], env['HTTP_CONTENT_ENCODING'])
22
+
23
+ env.delete('HTTP_CONTENT_ENCODING')
24
+ env['CONTENT_LENGTH'] = extracted.bytesize
25
+ env['rack.input'] = StringIO.new(extracted)
26
+ end
27
+
28
+ status, headers, response = @app.call(env)
29
+ return [status, headers, response]
30
+ end
31
+
32
+ def decode(input, content_encoding)
33
+ case content_encoding
34
+ when 'gzip' then Zlib::GzipReader.new(input).read
35
+ when 'deflate' then Zlib::Inflate.inflate(input.read)
36
+ end
37
+ end
38
+ 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.0.1
4
+ version: 5.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Elastic
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-08-16 00:00:00.000000000 Z
11
+ date: 2017-08-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement
@@ -108,6 +108,7 @@ files:
108
108
  - lib/logstash/outputs/http.rb
109
109
  - logstash-output-http.gemspec
110
110
  - spec/outputs/http_spec.rb
111
+ - spec/supports/compressed_requests.rb
111
112
  homepage: http://www.elastic.co/guide/en/logstash/current/index.html
112
113
  licenses:
113
114
  - Apache License (2.0)
@@ -136,3 +137,4 @@ specification_version: 4
136
137
  summary: This output lets you `PUT` or `POST` events to a generic HTTP(S) endpoint
137
138
  test_files:
138
139
  - spec/outputs/http_spec.rb
140
+ - spec/supports/compressed_requests.rb