fluent-plugin-http-puma 0.0.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 +7 -0
- data/.travis.yml +19 -0
- data/Gemfile +3 -0
- data/README.md +40 -0
- data/Rakefile +15 -0
- data/VERSION +1 -0
- data/fluent-plugin-http-puma.gemspec +23 -0
- data/lib/fluent/plugin/in_http_puma.rb +178 -0
- data/test/helper.rb +29 -0
- data/test/plugin/cert_puma.pem +19 -0
- data/test/plugin/puma_keypair.pem +15 -0
- data/test/plugin/test_in_http_puma.rb +209 -0
- metadata +100 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 57610401c51ad5e48c1a29aa19a1efa383d65b55
|
4
|
+
data.tar.gz: a9d505153b256aae456c914f367621f7e0fd1b12
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 458ccbac41fe5c06edc1e64a7fcbc01e65e83f2276023e950313e24c830577e9f01d7a0e36434e7de6bee6bd45cddb210e362fa7c74e043624b48a1aef00cf5a
|
7
|
+
data.tar.gz: e6e367fe5cf85ca046666dedee81ada2ad8b557f5bc287725bd05234f8e3c58e590175637728bba2275ce423efb094b2d38e09d4d43b15f6702329fbd1d324d4
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
# Puma based HTTP(S) plugin for Fluentd
|
2
|
+
|
3
|
+
HTTP input plugin based on [Puma](http://puma.io/)
|
4
|
+
|
5
|
+
This HTTP input plugin supports HTTPS mode.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Use RubyGems:
|
10
|
+
|
11
|
+
fluent-gem install fluent-plugin-http-puma
|
12
|
+
|
13
|
+
## Configuration
|
14
|
+
|
15
|
+
<source>
|
16
|
+
type http_puma
|
17
|
+
|
18
|
+
# optional parameters(same as in_http)
|
19
|
+
bind 127.0.0.1
|
20
|
+
port 9890
|
21
|
+
backlog 2048
|
22
|
+
format json
|
23
|
+
|
24
|
+
# optional Puma parameters
|
25
|
+
min_threads 0
|
26
|
+
max_threads 4
|
27
|
+
use_ssl
|
28
|
+
ssl_keys /path/to/key,/path/to/cert
|
29
|
+
</match>
|
30
|
+
|
31
|
+
### HTTPS mode
|
32
|
+
|
33
|
+
Use `use_ssl` and `ssl_keys`.
|
34
|
+
|
35
|
+
<source>
|
36
|
+
use_ssl
|
37
|
+
ssl_keys ["/path/to/key", "/path/to/cert"] # ssl_keys is required when use_ssl is true
|
38
|
+
</source>
|
39
|
+
|
40
|
+
`ssl_keys` are json array which has two elements, 1st is for key file, 2nd is for cert file.
|
data/Rakefile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
|
3
|
+
require 'bundler'
|
4
|
+
require 'bundler/gem_tasks'
|
5
|
+
Bundler::GemHelper.install_tasks
|
6
|
+
|
7
|
+
require 'rake/testtask'
|
8
|
+
|
9
|
+
Rake::TestTask.new(:test) do |test|
|
10
|
+
test.libs << 'lib' << 'test'
|
11
|
+
test.test_files = (Dir["test/plugin/test_*.rb"] - ["helper.rb"]).sort
|
12
|
+
test.verbose = true
|
13
|
+
end
|
14
|
+
|
15
|
+
task :default => [:build]
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.1
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
$:.push File.expand_path('../lib', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.name = "fluent-plugin-http-puma"
|
6
|
+
gem.description = "Puma based HTTP(S) plugin for Fluentd"
|
7
|
+
gem.homepage = "https://github.com/repeatedly/fluent-plugin-http-puma"
|
8
|
+
gem.summary = gem.description
|
9
|
+
gem.version = File.read("VERSION").strip
|
10
|
+
gem.authors = ["Masahiro Nakagawa"]
|
11
|
+
gem.email = "repeatedly@gmail.com"
|
12
|
+
gem.has_rdoc = false
|
13
|
+
#gem.platform = Gem::Platform::RUBY
|
14
|
+
gem.license = 'Apache License (2.0)'
|
15
|
+
gem.files = `git ls-files`.split("\n")
|
16
|
+
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
17
|
+
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
18
|
+
gem.require_paths = ['lib']
|
19
|
+
|
20
|
+
gem.add_dependency "fluentd", "~> 0.10.50"
|
21
|
+
gem.add_dependency "puma", "~> 2.9.0"
|
22
|
+
gem.add_development_dependency "rake", ">= 0.9.2"
|
23
|
+
end
|
@@ -0,0 +1,178 @@
|
|
1
|
+
module Fluent
|
2
|
+
class HttpPumaInput < Input
|
3
|
+
Plugin.register_input('http_puma', self)
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
require 'puma'
|
7
|
+
require 'uri'
|
8
|
+
super
|
9
|
+
end
|
10
|
+
|
11
|
+
config_param :port, :integer, :default => 9890
|
12
|
+
config_param :bind, :string, :default => '0.0.0.0'
|
13
|
+
config_param :min_threads, :integer, :default => 0
|
14
|
+
config_param :max_threads, :integer, :default => 4
|
15
|
+
config_param :use_ssl, :bool, :default => false
|
16
|
+
config_param :ssl_keys, :array, :default => nil
|
17
|
+
config_param :backlog, :integer, :default => nil
|
18
|
+
config_param :format, :string, :default => 'default'
|
19
|
+
|
20
|
+
def configure(conf)
|
21
|
+
super
|
22
|
+
|
23
|
+
if @use_ssl && !@ssl_keys
|
24
|
+
raise ConfigError, 'ssl_keys parameter is required when use_ssl is true'
|
25
|
+
end
|
26
|
+
|
27
|
+
if @format != 'default'
|
28
|
+
@parser = TextParser.new
|
29
|
+
@parser.configure(conf)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def start
|
34
|
+
super
|
35
|
+
|
36
|
+
# Refer puma's Runner and Rack handler for puma server setup
|
37
|
+
@server = ::Puma::Server.new(method(:on_request))
|
38
|
+
@server.min_threads = @min_threads
|
39
|
+
@server.max_threads = @max_threads
|
40
|
+
@server.leak_stack_on_error = false
|
41
|
+
if @use_ssl
|
42
|
+
setup_https
|
43
|
+
else
|
44
|
+
setup_http
|
45
|
+
end
|
46
|
+
|
47
|
+
@thread = Thread.new(&method(:run))
|
48
|
+
end
|
49
|
+
|
50
|
+
def shutdown
|
51
|
+
@server.stop(true)
|
52
|
+
@thread.join
|
53
|
+
end
|
54
|
+
|
55
|
+
def run
|
56
|
+
@server.run(false)
|
57
|
+
rescue => e
|
58
|
+
log.error "unexpected error", :error => e.to_s
|
59
|
+
log.error_backtrace e.backtrace
|
60
|
+
end
|
61
|
+
|
62
|
+
OK_RESPONSE = [200, {'Content-type'=>'text/plain'}, ["OK"]]
|
63
|
+
|
64
|
+
def on_request(env)
|
65
|
+
uri = URI.parse(env['REQUEST_URI'.freeze])
|
66
|
+
params = Rack::Utils.parse_query(uri.query)
|
67
|
+
path_info = uri.path
|
68
|
+
|
69
|
+
begin
|
70
|
+
path = path_info[1..-1] # remove /
|
71
|
+
tag = path.split('/').join('.')
|
72
|
+
record_time, record = parse_record(env, params)
|
73
|
+
|
74
|
+
# Skip nil record
|
75
|
+
if record.nil?
|
76
|
+
return OK_RESPONSE
|
77
|
+
end
|
78
|
+
|
79
|
+
time = if param_time = params['time'.freeze]
|
80
|
+
param_time = param_time.to_i
|
81
|
+
param_time.zero? ? Engine.now : param_time
|
82
|
+
else
|
83
|
+
record_time.nil? ? Engine.now : record_time
|
84
|
+
end
|
85
|
+
rescue => e
|
86
|
+
return [400, {'Content-type'=>'text/plain'}, ["Bad Request\n#{e}\n"]]
|
87
|
+
end
|
88
|
+
|
89
|
+
begin
|
90
|
+
# Support batched requests
|
91
|
+
if record.is_a?(Array)
|
92
|
+
mes = MultiEventStream.new
|
93
|
+
record.each do |single_record|
|
94
|
+
single_time = single_record.delete("time".freeze) || time
|
95
|
+
mes.add(single_time, single_record)
|
96
|
+
end
|
97
|
+
Engine.emit_stream(tag, mes)
|
98
|
+
else
|
99
|
+
Engine.emit(tag, time, record)
|
100
|
+
end
|
101
|
+
rescue => e
|
102
|
+
return [500, {'Content-type'=>'text/plain'}, ["Internal Server Error\n#{e}\n"]]
|
103
|
+
end
|
104
|
+
|
105
|
+
return OK_RESPONSE
|
106
|
+
end
|
107
|
+
|
108
|
+
private
|
109
|
+
|
110
|
+
def setup_http
|
111
|
+
log.info "listening http on #{@bind}:#{@port}"
|
112
|
+
|
113
|
+
opts = [@bind, @port, true]
|
114
|
+
opts << @backlog if @backlog
|
115
|
+
@server.add_tcp_listener(*opts)
|
116
|
+
end
|
117
|
+
|
118
|
+
def setup_https
|
119
|
+
require 'puma/minissl'
|
120
|
+
|
121
|
+
ctx = ::Puma::MiniSSL::Context.new
|
122
|
+
key, cert = @ssl_keys
|
123
|
+
if defined?(JRUBY_VERSION)
|
124
|
+
ctx.keystore = key
|
125
|
+
ctx.keystore_pass = cert
|
126
|
+
else
|
127
|
+
ctx.key = key
|
128
|
+
ctx.cert = cert
|
129
|
+
end
|
130
|
+
ctx.verify_mode = ::Puma::MiniSSL::VERIFY_PEER
|
131
|
+
#ctx.verify_mode = ::Puma::MiniSSL::VERIFY_NONE
|
132
|
+
|
133
|
+
log.info "listening https on #{@bind}:#{@port}"
|
134
|
+
|
135
|
+
opts = [@bind, @port, ctx, true]
|
136
|
+
opts << @backlog if @backlog
|
137
|
+
@server.add_ssl_listener(*opts)
|
138
|
+
end
|
139
|
+
|
140
|
+
def parse_record(env, params)
|
141
|
+
body = env['rack.input'.freeze]
|
142
|
+
content_type = env['CONTENT_TYPE'.freeze]
|
143
|
+
|
144
|
+
case
|
145
|
+
when @format != 'default'.freeze
|
146
|
+
parse_params_with_parser(body.read)
|
147
|
+
when content_type.start_with?('application/json'.freeze)
|
148
|
+
return nil, JSON.load(body)
|
149
|
+
when content_type.start_with?('application/x-msgpack'.freeze)
|
150
|
+
return nil, MessagePack.unpack(body)
|
151
|
+
when content_type =~ /^application\/x-www-form-urlencoded/
|
152
|
+
params.update(::Rack::Utils.parse_query(body.read))
|
153
|
+
parse_params_form(params)
|
154
|
+
when content_type =~ /^multipart\/form-data; boundary=(.+)/
|
155
|
+
params.update(::Rack::Multipart.parse_multipart(env))
|
156
|
+
parse_params_form(params)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
def parse_params_form(params)
|
161
|
+
record = if msgpack = params['msgpack'.freeze]
|
162
|
+
MessagePack.unpack(msgpack)
|
163
|
+
elsif js = params['json'.freeze]
|
164
|
+
JSON.parse(js)
|
165
|
+
else
|
166
|
+
raise "'json' or 'msgpack' parameter is required"
|
167
|
+
end
|
168
|
+
return nil, record
|
169
|
+
end
|
170
|
+
|
171
|
+
def parse_params_with_parser(content)
|
172
|
+
@parser.parse(content) { |time, record|
|
173
|
+
raise "received event is not #{@format}: #{content}" if record.nil?
|
174
|
+
return time, record
|
175
|
+
}
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'fluent/log'
|
4
|
+
require 'fluent/test'
|
5
|
+
|
6
|
+
unless defined?(Test::Unit::AssertionFailedError)
|
7
|
+
class Test::Unit::AssertionFailedError < StandardError
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def unused_port
|
12
|
+
s = TCPServer.open(0)
|
13
|
+
port = s.addr[1]
|
14
|
+
s.close
|
15
|
+
port
|
16
|
+
end
|
17
|
+
|
18
|
+
def ipv6_enabled?
|
19
|
+
require 'socket'
|
20
|
+
|
21
|
+
begin
|
22
|
+
TCPServer.open("::1", 0)
|
23
|
+
true
|
24
|
+
rescue
|
25
|
+
false
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
$log = Fluent::Log.new(Fluent::Test::DummyLogDevice.new, Fluent::Log::LEVEL_WARN)
|
@@ -0,0 +1,19 @@
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
2
|
+
MIIC/jCCAeagAwIBAgIBAjANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJVUzEO
|
3
|
+
MAwGA1UECgwFbG9jYWwxDTALBgNVBAsMBGFlcm8xCzAJBgNVBAMMAkNBMB4XDTEy
|
4
|
+
MDExNDAwMjcyN1oXDTEzMDExMzAwMjcyN1owSDELMAkGA1UEBhMCVVMxDjAMBgNV
|
5
|
+
BAoMBWxvY2FsMQ0wCwYDVQQLDARhZXJvMQswCQYDVQQLDAJDQTENMAsGA1UEAwwE
|
6
|
+
cHVtYTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArxfNMp+g/pKhsDEkB3KR
|
7
|
+
1MAkbfnN/UKMvfXwlnXpz7YX1LHHnMutiI/PqymAp6BPcu+umuW2qMHQyqqtyATm
|
8
|
+
Z9jr3t837nhmxwG1noRaKRtsckn9FD43ZlpPg0Q5QnhS4oOsXwJzilqPjdDFYrKN
|
9
|
+
3TSvIGM2+hVqpVoGYAHDKbMCAwEAAaOBhTCBgjAMBgNVHRMBAf8EAjAAMDEGCWCG
|
10
|
+
SAGG+EIBDQQkFiJSdWJ5L09wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0G
|
11
|
+
A1UdDgQWBBTyDyJlmYBDwfWdRj6lWGvoY43k9DALBgNVHQ8EBAMCBaAwEwYDVR0l
|
12
|
+
BAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQEFBQADggEBAIbBVfoVCG8RyVesPW+q
|
13
|
+
5i0wAMbHZ1fwv1RKp17c68DYDs0YYPi0bA0ss8AgpU6thWmskxPiFaE6D5x8iv9f
|
14
|
+
zkcHxgr1Mrbx6RLx9tLUVehSmRv3aiVO4k9Mp6vf+rJK1AYeaGBmvoqTBLwy7Jrt
|
15
|
+
ytKMdqMJj5jKWkWgEGgTnjzbcOClmCQab9isigIzTxMyC/LjeKZe8pPeVX6OM8bY
|
16
|
+
y8XGZp9B7uwdPzqt/g25IzTC0KsQwq8cB0raAtZzIyTNv42zcUjmQNVazAozCTcq
|
17
|
+
MsEtK2z7TYBC3udTsdyS2qVqCpsk7IMOBGrw8vk4SNhO+coiDObW2K/HNvhl0tZC
|
18
|
+
oQI=
|
19
|
+
-----END CERTIFICATE-----
|
@@ -0,0 +1,15 @@
|
|
1
|
+
-----BEGIN RSA PRIVATE KEY-----
|
2
|
+
MIICXQIBAAKBgQCvF80yn6D+kqGwMSQHcpHUwCRt+c39Qoy99fCWdenPthfUscec
|
3
|
+
y62Ij8+rKYCnoE9y766a5baowdDKqq3IBOZn2Ove3zfueGbHAbWehFopG2xySf0U
|
4
|
+
PjdmWk+DRDlCeFLig6xfAnOKWo+N0MViso3dNK8gYzb6FWqlWgZgAcMpswIDAQAB
|
5
|
+
AoGAHv/UyZivdULas4oPue3T2dnm2T239ZXZuywW21ym96pij7ql/6Gj6KClgMVJ
|
6
|
+
TOQ6DLxYqn3vF/OwlqEfQWF0tTUYY+xNbEDE1YsbrS5/FSzbaEYYOHzRl/vMmnsf
|
7
|
+
aNgYaSjOIecin7L71Wzq0piMIxg8BLb6IVECBku9EQNzxuECQQDZsbRgg1XZGj+r
|
8
|
+
XAu/qXTNKQ/r7k+iPN5bXON6ApBomG+4Q7VVITL3tkGzLOphRZ37Q28FrN4B4gtC
|
9
|
+
Xb9il5lDAkEAzecTSopPi2VdcME4WWmwn1rbTp/jJNt4dGZLsNfj9RejVDd32i/L
|
10
|
+
P7wCpoPDaaVcoF2HgvCs39qatyVg6ecu0QJBALN4q+q9nDMGTuNpWU5D2EWjyrqJ
|
11
|
+
mCF66R6NcASQxJlWwxQ4zfBHFIvgOD4Nk5VqHZqet5MIN2d6AipOu4/+x50CQHDp
|
12
|
+
jf+rd1GHBcXGf8MwnUXWCjvEnEhi/lw+mLVivsRx8QRG4rfIy9monX949Flj8DaU
|
13
|
+
87IPj422kG9s1QeP2nECQQCkg+RUcoQm7SiM8OXuXNeHQlvQNp65geFRxzKAXxT/
|
14
|
+
+1Mbtwnd3AXXZBekFDDpE9U3ZQjahoe7oc1oUBuw5hXL
|
15
|
+
-----END RSA PRIVATE KEY-----
|
@@ -0,0 +1,209 @@
|
|
1
|
+
require 'helper'
|
2
|
+
require 'fluent/plugin/in_http_puma'
|
3
|
+
require 'net/https'
|
4
|
+
|
5
|
+
class HttpPumaInputTest < Test::Unit::TestCase
|
6
|
+
def setup
|
7
|
+
Fluent::Test.setup
|
8
|
+
end
|
9
|
+
|
10
|
+
PORT = unused_port
|
11
|
+
CONFIG = %[
|
12
|
+
port #{PORT}
|
13
|
+
bind "127.0.0.1"
|
14
|
+
]
|
15
|
+
|
16
|
+
def create_driver(conf = CONFIG)
|
17
|
+
Fluent::Test::InputTestDriver.new(Fluent::HttpPumaInput).configure(conf, true)
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_configure
|
21
|
+
d = create_driver
|
22
|
+
assert_equal PORT, d.instance.port
|
23
|
+
assert_equal '127.0.0.1', d.instance.bind
|
24
|
+
assert_equal false, d.instance.use_ssl
|
25
|
+
assert_equal 0, d.instance.min_threads
|
26
|
+
assert_equal 4, d.instance.max_threads
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_time
|
30
|
+
d = create_driver
|
31
|
+
|
32
|
+
time = Time.parse("2011-01-02 13:14:15 UTC").to_i
|
33
|
+
Fluent::Engine.now = time
|
34
|
+
|
35
|
+
d.expect_emit "tag1", time, {"a" => 1}
|
36
|
+
d.expect_emit "tag2", time, {"a" => 2}
|
37
|
+
|
38
|
+
d.run do
|
39
|
+
d.expected_emits.each { |tag, time, record|
|
40
|
+
res = post("/#{tag}", {"json" => record.to_json})
|
41
|
+
assert_equal "200", res.code
|
42
|
+
}
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_json
|
47
|
+
d = create_driver
|
48
|
+
|
49
|
+
time = Time.parse("2011-01-02 13:14:15 UTC").to_i
|
50
|
+
|
51
|
+
d.expect_emit "tag1", time, {"a" => 1}
|
52
|
+
d.expect_emit "tag2", time, {"a" => 2}
|
53
|
+
|
54
|
+
d.run do
|
55
|
+
d.expected_emits.each { |tag,time,record|
|
56
|
+
res = post("/#{tag}", {"json" => record.to_json, "time" => time.to_s})
|
57
|
+
assert_equal "200", res.code
|
58
|
+
}
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# puma_keypair.pem and cert_puma.pem are from puma's repository
|
63
|
+
def test_json_over_https
|
64
|
+
dir = File.dirname(__FILE__)
|
65
|
+
d = create_driver(CONFIG + %[
|
66
|
+
use_ssl
|
67
|
+
ssl_keys ["#{File.join(dir, 'puma_keypair.pem')}", "#{File.join(dir, 'cert_puma.pem')}"]
|
68
|
+
])
|
69
|
+
|
70
|
+
time = Time.parse("2011-01-02 13:14:15 UTC").to_i
|
71
|
+
|
72
|
+
d.expect_emit "tag1", time, {"a" => 1}
|
73
|
+
d.expect_emit "tag2", time, {"a" => 2}
|
74
|
+
|
75
|
+
d.run do
|
76
|
+
d.expected_emits.each { |tag,time,record|
|
77
|
+
res = post("/#{tag}", {"json" => record.to_json, "time" => time.to_s}, {}, true)
|
78
|
+
assert_equal "200", res.code
|
79
|
+
}
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_multi_json
|
84
|
+
d = create_driver
|
85
|
+
|
86
|
+
time = Time.parse("2011-01-02 13:14:15 UTC").to_i
|
87
|
+
|
88
|
+
events = [{"a" => 1},{"a" => 2}]
|
89
|
+
tag = "tag1"
|
90
|
+
|
91
|
+
events.each { |ev|
|
92
|
+
d.expect_emit tag, time, ev
|
93
|
+
}
|
94
|
+
|
95
|
+
d.run do
|
96
|
+
res = post("/#{tag}", {"json" => events.to_json, "time" => time.to_s})
|
97
|
+
assert_equal "200", res.code
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def test_application_json
|
102
|
+
d = create_driver
|
103
|
+
|
104
|
+
time = Time.parse("2011-01-02 13:14:15 UTC").to_i
|
105
|
+
|
106
|
+
d.expect_emit "tag1", time, {"a" => 1}
|
107
|
+
d.expect_emit "tag2", time, {"a" => 2}
|
108
|
+
|
109
|
+
d.run do
|
110
|
+
d.expected_emits.each {|tag,time,record|
|
111
|
+
res = post("/#{tag}?time=#{time.to_s}", record.to_json, {"content-type" => "application/json; charset=utf-8"})
|
112
|
+
assert_equal "200", res.code
|
113
|
+
}
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def test_msgpack
|
118
|
+
d = create_driver
|
119
|
+
|
120
|
+
time = Time.parse("2011-01-02 13:14:15 UTC").to_i
|
121
|
+
|
122
|
+
d.expect_emit "tag1", time, {"a" => 1}
|
123
|
+
d.expect_emit "tag2", time, {"a" => 2}
|
124
|
+
|
125
|
+
d.run do
|
126
|
+
d.expected_emits.each {|tag,time,record|
|
127
|
+
res = post("/#{tag}", {"msgpack" => record.to_msgpack, "time" => time.to_s})
|
128
|
+
assert_equal "200", res.code
|
129
|
+
}
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def test_multi_msgpack
|
134
|
+
d = create_driver
|
135
|
+
|
136
|
+
time = Time.parse("2011-01-02 13:14:15 UTC").to_i
|
137
|
+
events = [{"a" => 1},{"a" => 2}]
|
138
|
+
tag = "tag1"
|
139
|
+
|
140
|
+
events.each { |ev|
|
141
|
+
d.expect_emit tag, time, ev
|
142
|
+
}
|
143
|
+
|
144
|
+
d.run do
|
145
|
+
res = post("/#{tag}", {"msgpack" => events.to_msgpack, "time" => time.to_s})
|
146
|
+
assert_equal "200", res.code
|
147
|
+
end
|
148
|
+
|
149
|
+
end
|
150
|
+
|
151
|
+
def test_with_regexp
|
152
|
+
d = create_driver(CONFIG + %[
|
153
|
+
format /^(?<field_1>\\\\d+):(?<field_2>\\\\w+)$/
|
154
|
+
types field_1:integer
|
155
|
+
])
|
156
|
+
|
157
|
+
time = Time.parse("2011-01-02 13:14:15 UTC").to_i
|
158
|
+
|
159
|
+
d.expect_emit "tag1", time, {"field_1" => 1, "field_2" => 'str'}
|
160
|
+
d.expect_emit "tag2", time, {"field_1" => 2, "field_2" => 'str'}
|
161
|
+
|
162
|
+
d.run do
|
163
|
+
d.expected_emits.each { |tag, time, record|
|
164
|
+
body = record.map { |k, v|
|
165
|
+
v.to_s
|
166
|
+
}.join(':')
|
167
|
+
res = post("/#{tag}?time=#{time.to_s}", body)
|
168
|
+
assert_equal "200", res.code
|
169
|
+
}
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
def test_with_csv
|
174
|
+
require 'csv'
|
175
|
+
|
176
|
+
d = create_driver(CONFIG + %[
|
177
|
+
format csv
|
178
|
+
keys foo,bar
|
179
|
+
])
|
180
|
+
|
181
|
+
time = Time.parse("2011-01-02 13:14:15 UTC").to_i
|
182
|
+
|
183
|
+
d.expect_emit "tag1", time, {"foo" => "1", "bar" => 'st"r'}
|
184
|
+
d.expect_emit "tag2", time, {"foo" => "2", "bar" => 'str'}
|
185
|
+
|
186
|
+
d.run do
|
187
|
+
d.expected_emits.each { |tag, time, record|
|
188
|
+
body = record.map { |k, v| v }.to_csv
|
189
|
+
res = post("/#{tag}?time=#{time.to_s}", body)
|
190
|
+
assert_equal "200", res.code
|
191
|
+
}
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
def post(path, params, header = {}, ssl = false)
|
196
|
+
http = Net::HTTP.new("127.0.0.1", PORT)
|
197
|
+
if ssl
|
198
|
+
http.use_ssl = true
|
199
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
200
|
+
end
|
201
|
+
req = Net::HTTP::Post.new(path, header)
|
202
|
+
if params.is_a?(String)
|
203
|
+
req.body = params
|
204
|
+
else
|
205
|
+
req.set_form_data(params)
|
206
|
+
end
|
207
|
+
http.request(req)
|
208
|
+
end
|
209
|
+
end
|
metadata
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: fluent-plugin-http-puma
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Masahiro Nakagawa
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-07-19 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: fluentd
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.10.50
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.10.50
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: puma
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 2.9.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 2.9.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 0.9.2
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.9.2
|
55
|
+
description: Puma based HTTP(S) plugin for Fluentd
|
56
|
+
email: repeatedly@gmail.com
|
57
|
+
executables: []
|
58
|
+
extensions: []
|
59
|
+
extra_rdoc_files: []
|
60
|
+
files:
|
61
|
+
- ".travis.yml"
|
62
|
+
- Gemfile
|
63
|
+
- README.md
|
64
|
+
- Rakefile
|
65
|
+
- VERSION
|
66
|
+
- fluent-plugin-http-puma.gemspec
|
67
|
+
- lib/fluent/plugin/in_http_puma.rb
|
68
|
+
- test/helper.rb
|
69
|
+
- test/plugin/cert_puma.pem
|
70
|
+
- test/plugin/puma_keypair.pem
|
71
|
+
- test/plugin/test_in_http_puma.rb
|
72
|
+
homepage: https://github.com/repeatedly/fluent-plugin-http-puma
|
73
|
+
licenses:
|
74
|
+
- Apache License (2.0)
|
75
|
+
metadata: {}
|
76
|
+
post_install_message:
|
77
|
+
rdoc_options: []
|
78
|
+
require_paths:
|
79
|
+
- lib
|
80
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
81
|
+
requirements:
|
82
|
+
- - ">="
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: '0'
|
85
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
requirements: []
|
91
|
+
rubyforge_project:
|
92
|
+
rubygems_version: 2.2.2
|
93
|
+
signing_key:
|
94
|
+
specification_version: 4
|
95
|
+
summary: Puma based HTTP(S) plugin for Fluentd
|
96
|
+
test_files:
|
97
|
+
- test/helper.rb
|
98
|
+
- test/plugin/cert_puma.pem
|
99
|
+
- test/plugin/puma_keypair.pem
|
100
|
+
- test/plugin/test_in_http_puma.rb
|