logstash-input-http 3.1.0-java → 3.2.0-java
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 +4 -4
- data/CHANGELOG.md +6 -0
- data/VERSION +1 -1
- data/docs/index.asciidoc +16 -0
- data/lib/logstash-input-http_jars.rb +1 -1
- data/lib/logstash/inputs/http.rb +16 -34
- data/lib/logstash/inputs/http/message_handler.rb +11 -21
- data/spec/inputs/http_spec.rb +92 -1
- data/vendor/jar-dependencies/org/logstash/plugins/input/http/logstash-input-http/{3.1.0/logstash-input-http-3.1.0.jar → 3.2.0/logstash-input-http-3.2.0.jar} +0 -0
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dd4ab63a8da778ab6b98669f405773f04defba698bef77a3430d0ea4eb778cf0
|
4
|
+
data.tar.gz: 8bc8d4d7909fa768424d63142198644bb97e6b8ea44bef779288267d48044052
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 91ee9ad30eaf383efbf38b2f8a6720a3a9bba045ed7dda602734600dfa63b6d7c532bbee12b078a6c1444632e7edb3afe19569d72e9f2f4e94405092849d4a6c
|
7
|
+
data.tar.gz: b09f089df723d4240a6a89d8c78cb46c54a914784d8a15491604be7b31238c4f668044ea15f3cceb74e557f70678783ff0b4c9444ba8d61c56d55f0f8bd844c8
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
## 3.2.0
|
2
|
+
- Add `request_headers_target_field` and `remote_host_target_field` configuration options with default to `host` and `headers` respectively #68
|
3
|
+
- Sanitize content-type header with getMimeType #87
|
4
|
+
- Move most message handling code to java #85
|
5
|
+
- Fix: respond with correct http protocol version #84
|
6
|
+
|
1
7
|
## 3.1.0
|
2
8
|
- Replace Puma web server with Netty
|
3
9
|
- Support crt/key certificates
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.
|
1
|
+
3.2.0
|
data/docs/index.asciidoc
CHANGED
@@ -184,6 +184,22 @@ Persistent Queue for the logstash pipeline.
|
|
184
184
|
|
185
185
|
specify a custom set of response headers
|
186
186
|
|
187
|
+
[id="plugins-{type}s-{plugin}-remote_host_target_field"]
|
188
|
+
===== `remote_host_target_field`
|
189
|
+
|
190
|
+
* Value type is <<string,string>>
|
191
|
+
* Default value is `"host"`
|
192
|
+
|
193
|
+
specify a target field for the client host of the http request
|
194
|
+
|
195
|
+
[id="plugins-{type}s-{plugin}-request_headers_target_field"]
|
196
|
+
===== `request_headers_target_field`
|
197
|
+
|
198
|
+
* Value type is <<string,string>>
|
199
|
+
* Default value is `"headers"`
|
200
|
+
|
201
|
+
specify target field for the client host of the http request
|
202
|
+
|
187
203
|
[id="plugins-{type}s-{plugin}-ssl"]
|
188
204
|
===== `ssl`
|
189
205
|
|
@@ -4,4 +4,4 @@ require 'jar_dependencies'
|
|
4
4
|
require_jar('io.netty', 'netty-all', '4.1.18.Final')
|
5
5
|
require_jar('io.netty', 'netty-tcnative-boringssl-static', '2.0.7.Final')
|
6
6
|
require_jar('org.apache.logging.log4j', 'log4j-api', '2.6.2')
|
7
|
-
require_jar('org.logstash.plugins.input.http', 'logstash-input-http', '3.
|
7
|
+
require_jar('org.logstash.plugins.input.http', 'logstash-input-http', '3.2.0')
|
data/lib/logstash/inputs/http.rb
CHANGED
@@ -4,6 +4,8 @@ require "logstash/namespace"
|
|
4
4
|
require "stud/interval"
|
5
5
|
require "logstash-input-http_jars"
|
6
6
|
|
7
|
+
java_import "io.netty.handler.codec.http.HttpUtil"
|
8
|
+
|
7
9
|
# Using this input you can receive single or multiline events over http(s).
|
8
10
|
# Applications can send a HTTP POST request with a body to the endpoint started by this
|
9
11
|
# input and Logstash will convert it into an event for subsequent processing. Users
|
@@ -101,6 +103,12 @@ class LogStash::Inputs::Http < LogStash::Inputs::Base
|
|
101
103
|
# specify a custom set of response headers
|
102
104
|
config :response_headers, :validate => :hash, :default => { 'Content-Type' => 'text/plain' }
|
103
105
|
|
106
|
+
# target field for the client host of the http request
|
107
|
+
config :remote_host_target_field, :validate => :string, :default => "host"
|
108
|
+
|
109
|
+
# target field for the client host of the http request
|
110
|
+
config :request_headers_target_field, :validate => :string, :default => "headers"
|
111
|
+
|
104
112
|
config :threads, :validate => :number, :required => false, :default => ::LogStash::Config::CpuCoreStrategy.maximum
|
105
113
|
|
106
114
|
config :max_pending_requests, :validate => :number, :required => false, :default => 200
|
@@ -133,7 +141,7 @@ class LogStash::Inputs::Http < LogStash::Inputs::Base
|
|
133
141
|
end
|
134
142
|
|
135
143
|
require "logstash/inputs/http/message_handler"
|
136
|
-
message_handler = MessageHandler.new(self, @codec, @codecs)
|
144
|
+
message_handler = MessageHandler.new(self, @codec, @codecs, @auth_token)
|
137
145
|
@http_server = create_http_server(message_handler)
|
138
146
|
end # def register
|
139
147
|
|
@@ -151,23 +159,12 @@ class LogStash::Inputs::Http < LogStash::Inputs::Base
|
|
151
159
|
@http_server.close() rescue nil
|
152
160
|
end
|
153
161
|
|
154
|
-
def decode_body(remote_address,
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
http_full_request.headers.each do |header|
|
159
|
-
headers[header.key.downcase.tr('-', '_')] = header.value
|
160
|
-
end
|
161
|
-
headers["request_method"] = http_full_request.getMethod.name
|
162
|
-
headers["request_path"] = http_full_request.getUri
|
163
|
-
headers["http_version"] = http_full_request.getProtocolVersion.text
|
164
|
-
headers["http_accept"] = headers.delete("accept")
|
165
|
-
headers["http_host"] = headers.delete("host")
|
166
|
-
headers["http_user_agent"] = headers.delete("user_agent")
|
167
|
-
codec = additional_codecs.fetch(headers["content_type"], default_codec)
|
162
|
+
def decode_body(headers, remote_address, body, default_codec, additional_codecs)
|
163
|
+
content_type = headers.fetch("content_type", "")
|
164
|
+
codec = additional_codecs.fetch(HttpUtil.getMimeType(content_type), default_codec)
|
168
165
|
codec.decode(body) { |event| push_decoded_event(headers, remote_address, event) }
|
169
166
|
codec.flush { |event| push_decoded_event(headers, remote_address, event) }
|
170
|
-
|
167
|
+
true
|
171
168
|
rescue => e
|
172
169
|
@logger.error(
|
173
170
|
"unable to process event.",
|
@@ -175,31 +172,16 @@ class LogStash::Inputs::Http < LogStash::Inputs::Base
|
|
175
172
|
:class => e.class.name,
|
176
173
|
:backtrace => e.backtrace
|
177
174
|
)
|
178
|
-
|
175
|
+
false
|
179
176
|
end
|
180
177
|
|
181
178
|
def push_decoded_event(headers, remote_address, event)
|
182
|
-
event.set(
|
183
|
-
event.set(
|
179
|
+
event.set(@request_headers_target_field, headers)
|
180
|
+
event.set(@remote_host_target_field, remote_address)
|
184
181
|
decorate(event)
|
185
182
|
@queue << event
|
186
183
|
end
|
187
184
|
|
188
|
-
def valid_auth?(token)
|
189
|
-
if @auth_token
|
190
|
-
@auth_token == token
|
191
|
-
else
|
192
|
-
true
|
193
|
-
end
|
194
|
-
end
|
195
|
-
|
196
|
-
private
|
197
|
-
def read_bytes(bytebuffer)
|
198
|
-
bytes = Java::byte[bytebuffer.readableBytes].new
|
199
|
-
bytebuffer.getBytes(0, bytes)
|
200
|
-
String.from_java_bytes(bytes, "ASCII-8BIT")
|
201
|
-
end
|
202
|
-
|
203
185
|
def validate_ssl_settings!
|
204
186
|
if !@ssl
|
205
187
|
@logger.warn("SSL Certificate will not be used") if @ssl_certificate
|
@@ -14,37 +14,27 @@ module LogStash module Inputs class Http
|
|
14
14
|
|
15
15
|
attr_reader :input
|
16
16
|
|
17
|
-
def initialize(input, default_codec, additional_codecs)
|
17
|
+
def initialize(input, default_codec, additional_codecs, auth_token)
|
18
18
|
@input = input
|
19
19
|
@default_codec = default_codec
|
20
20
|
@additional_codecs = additional_codecs
|
21
|
+
@auth_token = auth_token
|
21
22
|
end
|
22
23
|
|
23
|
-
def
|
24
|
-
if
|
25
|
-
|
26
|
-
status, headers, content = @input.decode_body(remote_address, message, @default_codec, @additional_codecs)
|
24
|
+
def validates_token(token)
|
25
|
+
if @auth_token
|
26
|
+
@auth_token == token
|
27
27
|
else
|
28
|
-
|
28
|
+
true
|
29
29
|
end
|
30
|
-
generate_response(status, headers, content)
|
31
30
|
end
|
32
31
|
|
33
|
-
|
34
|
-
|
35
|
-
payload = Unpooled.copiedBuffer(content.to_java_string, CharsetUtil::UTF_8)
|
36
|
-
response = DefaultFullHttpResponse.new(
|
37
|
-
HttpVersion::HTTP_1_1,
|
38
|
-
HttpResponseStatus.valueOf(status),
|
39
|
-
payload)
|
40
|
-
response.headers().set(HttpHeaderNames::CONTENT_LENGTH, payload.readable_bytes());
|
41
|
-
response.headers().set(HttpHeaderNames::CONTENT_TYPE, "text/plain");
|
42
|
-
headers.each { |k, v| response.headers().set(k, v) }
|
43
|
-
response
|
32
|
+
def onNewMessage(remote_address, headers, body)
|
33
|
+
@input.decode_body(headers, remote_address, body, @default_codec, @additional_codecs)
|
44
34
|
end
|
45
35
|
|
46
36
|
def copy
|
47
|
-
MessageHandler.new(@input, @default_codec.clone, clone_additional_codecs())
|
37
|
+
MessageHandler.new(@input, @default_codec.clone, clone_additional_codecs(), @auth_token)
|
48
38
|
end
|
49
39
|
|
50
40
|
def clone_additional_codecs
|
@@ -55,8 +45,8 @@ module LogStash module Inputs class Http
|
|
55
45
|
clone_additional_codecs
|
56
46
|
end
|
57
47
|
|
58
|
-
def
|
59
|
-
@input.
|
48
|
+
def response_headers
|
49
|
+
@input.response_headers
|
60
50
|
end
|
61
51
|
end
|
62
52
|
end; end; end
|
data/spec/inputs/http_spec.rb
CHANGED
@@ -29,6 +29,7 @@ describe LogStash::Inputs::Http do
|
|
29
29
|
|
30
30
|
describe "request handling" do
|
31
31
|
subject { LogStash::Inputs::Http.new("port" => port) }
|
32
|
+
|
32
33
|
before :each do
|
33
34
|
subject.register
|
34
35
|
t = Thread.new { subject.run(logstash_queue) }
|
@@ -81,6 +82,57 @@ describe LogStash::Inputs::Http do
|
|
81
82
|
end
|
82
83
|
end
|
83
84
|
|
85
|
+
describe "remote host" do
|
86
|
+
subject { LogStash::Inputs::Http.new(config.merge("port" => port)) }
|
87
|
+
context "by default" do
|
88
|
+
let(:config) { {} }
|
89
|
+
it "is written to the \"host\" field" do
|
90
|
+
client.post("http://localhost:#{port}/meh.json",
|
91
|
+
:headers => { "content-type" => "text/plain" },
|
92
|
+
:body => "hello").call
|
93
|
+
event = logstash_queue.pop
|
94
|
+
expect(event.get("host")).to eq("127.0.0.1")
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
context "when using remote_host_target_field" do
|
99
|
+
let(:config) { { "remote_host_target_field" => "remote_host" } }
|
100
|
+
it "is written to the value of \"remote_host_target_field\" property" do
|
101
|
+
client.post("http://localhost:#{port}/meh.json",
|
102
|
+
:headers => { "content-type" => "text/plain" },
|
103
|
+
:body => "hello").call
|
104
|
+
event = logstash_queue.pop
|
105
|
+
expect(event.get("remote_host")).to eq("127.0.0.1")
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
describe "request headers" do
|
111
|
+
subject { LogStash::Inputs::Http.new(config.merge("port" => port)) }
|
112
|
+
context "by default" do
|
113
|
+
let(:config) { {} }
|
114
|
+
it "are written to the \"headers\" field" do
|
115
|
+
client.post("http://localhost:#{port}/meh.json",
|
116
|
+
:headers => { "content-type" => "text/plain" },
|
117
|
+
:body => "hello").call
|
118
|
+
event = logstash_queue.pop
|
119
|
+
expect(event.get("headers")).to be_a(Hash)
|
120
|
+
expect(event.get("headers")).to include("request_method" => "POST")
|
121
|
+
end
|
122
|
+
end
|
123
|
+
context "when using request_headers_target_field" do
|
124
|
+
let(:config) { { "request_headers_target_field" => "request_headers" } }
|
125
|
+
it "are written to the field set in \"request_headers_target_field\"" do
|
126
|
+
client.post("http://localhost:#{port}/meh.json",
|
127
|
+
:headers => { "content-type" => "text/plain" },
|
128
|
+
:body => "hello").call
|
129
|
+
event = logstash_queue.pop
|
130
|
+
expect(event.get("request_headers")).to be_a(Hash)
|
131
|
+
expect(event.get("request_headers")).to include("request_method" => "POST")
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
84
136
|
it "should include remote host in \"host\" property" do
|
85
137
|
client.post("http://127.0.0.1:#{port}/meh.json",
|
86
138
|
:headers => { "content-type" => "text/plain" },
|
@@ -190,6 +242,19 @@ describe LogStash::Inputs::Http do
|
|
190
242
|
expect(event.get("message")).to eq(body)
|
191
243
|
end
|
192
244
|
end
|
245
|
+
|
246
|
+
context "when receiving a content-type with a charset" do
|
247
|
+
subject { LogStash::Inputs::Http.new("port" => port,
|
248
|
+
"additional_codecs" => { "application/json" => "plain" }) }
|
249
|
+
it "should decode the message accordingly" do
|
250
|
+
body = { "message" => "Hello" }.to_json
|
251
|
+
client.post("http://127.0.0.1:#{port}/meh.json",
|
252
|
+
:headers => { "content-type" => "application/json; charset=utf-8" },
|
253
|
+
:body => body).call
|
254
|
+
event = logstash_queue.pop
|
255
|
+
expect(event.get("message")).to eq(body)
|
256
|
+
end
|
257
|
+
end
|
193
258
|
|
194
259
|
context "when using custom headers" do
|
195
260
|
let(:custom_headers) { { 'access-control-allow-origin' => '*' } }
|
@@ -197,7 +262,7 @@ describe LogStash::Inputs::Http do
|
|
197
262
|
|
198
263
|
describe "the response" do
|
199
264
|
it "should include the custom headers" do
|
200
|
-
response = client.post("http://127.0.0.1:#{port}/meh", :body => "hello")
|
265
|
+
response = client.post("http://127.0.0.1:#{port}/meh", :body => "hello").call
|
201
266
|
expect(response.headers.to_hash).to include(custom_headers)
|
202
267
|
end
|
203
268
|
end
|
@@ -248,6 +313,32 @@ describe LogStash::Inputs::Http do
|
|
248
313
|
end
|
249
314
|
end
|
250
315
|
|
316
|
+
describe "HTTP Protocol Handling" do
|
317
|
+
context "when an HTTP1.1 request is made" do
|
318
|
+
let(:protocol_version) do
|
319
|
+
Java::OrgApacheHttp::HttpVersion::HTTP_1_1
|
320
|
+
end
|
321
|
+
it "responds with a HTTP1.1 response" do
|
322
|
+
response = client.post("http://127.0.0.1:#{port}", :body => "hello")
|
323
|
+
response.request.set_protocol_version(protocol_version)
|
324
|
+
response.call
|
325
|
+
response_protocol_version = response.instance_variable_get(:@response).get_protocol_version
|
326
|
+
expect(response_protocol_version).to eq(protocol_version)
|
327
|
+
end
|
328
|
+
end
|
329
|
+
context "when an HTTP1.0 request is made" do
|
330
|
+
let(:protocol_version) do
|
331
|
+
Java::OrgApacheHttp::HttpVersion::HTTP_1_0
|
332
|
+
end
|
333
|
+
it "responds with a HTTP1.0 response" do
|
334
|
+
response = client.post("http://127.0.0.1:#{port}", :body => "hello")
|
335
|
+
response.request.set_protocol_version(protocol_version)
|
336
|
+
response.call
|
337
|
+
response_protocol_version = response.instance_variable_get(:@response).get_protocol_version
|
338
|
+
expect(response_protocol_version).to eq(protocol_version)
|
339
|
+
end
|
340
|
+
end
|
341
|
+
end
|
251
342
|
end
|
252
343
|
|
253
344
|
context "with :ssl => false" do
|
Binary file
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: logstash-input-http
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.2.0
|
5
5
|
platform: java
|
6
6
|
authors:
|
7
7
|
- Elastic
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-05-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
@@ -141,7 +141,7 @@ files:
|
|
141
141
|
- vendor/jar-dependencies/io/netty/netty-all/4.1.18.Final/netty-all-4.1.18.Final.jar
|
142
142
|
- vendor/jar-dependencies/io/netty/netty-tcnative-boringssl-static/2.0.7.Final/netty-tcnative-boringssl-static-2.0.7.Final.jar
|
143
143
|
- vendor/jar-dependencies/org/apache/logging/log4j/log4j-api/2.6.2/log4j-api-2.6.2.jar
|
144
|
-
- vendor/jar-dependencies/org/logstash/plugins/input/http/logstash-input-http/3.
|
144
|
+
- vendor/jar-dependencies/org/logstash/plugins/input/http/logstash-input-http/3.2.0/logstash-input-http-3.2.0.jar
|
145
145
|
homepage: http://www.elastic.co/guide/en/logstash/current/index.html
|
146
146
|
licenses:
|
147
147
|
- Apache License (2.0)
|
@@ -165,7 +165,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
165
165
|
version: '0'
|
166
166
|
requirements: []
|
167
167
|
rubyforge_project:
|
168
|
-
rubygems_version: 2.6.
|
168
|
+
rubygems_version: 2.6.13
|
169
169
|
signing_key:
|
170
170
|
specification_version: 4
|
171
171
|
summary: Receives events over HTTP or HTTPS
|