fluent-plugin-http-puma 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|