fluent-plugin-http-list 0.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.
- data/.gitignore +19 -0
- data/Gemfile +3 -0
- data/LICENSE +20 -0
- data/README.md +42 -0
- data/Rakefile +11 -0
- data/fluent-plugin-http-list.gemspec +18 -0
- data/lib/fluent/plugin/in_http_list.rb +269 -0
- data/test/plugin/test_in_http_list.rb +156 -0
- metadata +86 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Fluent HTTP List plugin
|
|
3
|
+
#
|
|
4
|
+
# Copyright 2013 M3, Inc.
|
|
5
|
+
# Written by Paul McCann (p-mccann@m3.com)
|
|
6
|
+
# Based on the HTTP Input Plugin by FURUHASHI Sadayuki included with Fluentd
|
|
7
|
+
#
|
|
8
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
9
|
+
# you may not use this file except in compliance with the License.
|
|
10
|
+
# You may obtain a copy of the License at
|
|
11
|
+
#
|
|
12
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
13
|
+
#
|
|
14
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
15
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
16
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
17
|
+
# See the License for the specific language governing permissions and
|
|
18
|
+
# limitations under the License.
|
|
19
|
+
##
|
|
20
|
+
|
data/README.md
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# fluent-plugin-http-list
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
This plugin takes a JSON list of events as input via HTTP POST. If you're
|
|
6
|
+
sending a lot of events this simplifies your client's code and eliminates
|
|
7
|
+
the overhead of creating a lot of brief connections.
|
|
8
|
+
|
|
9
|
+
※ Note that unlike the default HTTP plugin, this does *not* support msgpack.
|
|
10
|
+
|
|
11
|
+
## Configuration
|
|
12
|
+
|
|
13
|
+
The HttpListInput plugin uses the same settings you would use for the standard
|
|
14
|
+
HTTP input plugin. Example:
|
|
15
|
+
|
|
16
|
+
<source>
|
|
17
|
+
type http_list
|
|
18
|
+
port 8888
|
|
19
|
+
bind 0.0.0.0
|
|
20
|
+
body_size_limit 32m
|
|
21
|
+
keepalive_timeout 10s
|
|
22
|
+
</source>
|
|
23
|
+
|
|
24
|
+
Like the HTTP input plugin, the tag is determined by the URL used, which means
|
|
25
|
+
all events in one request must have the same tag.
|
|
26
|
+
|
|
27
|
+
## Usage
|
|
28
|
+
|
|
29
|
+
Have your logging system send JSON lists of events. Example:
|
|
30
|
+
|
|
31
|
+
curl -X POST -d 'json=[{"fish":"catfish","user":23},{"fish":"elephantfish","user":23}]' \
|
|
32
|
+
http://localhost:8888/fish.tracker
|
|
33
|
+
|
|
34
|
+
Each event will go to your output plugins as an individual event.
|
|
35
|
+
|
|
36
|
+
## Copyright
|
|
37
|
+
|
|
38
|
+
Copyright (c) 2013 M3, Inc.
|
|
39
|
+
|
|
40
|
+
Based on the in_http plugin by FURUHASHI Sadayuki
|
|
41
|
+
|
|
42
|
+
Apache License, Version 2.0
|
data/Rakefile
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
Gem::Specification.new do |gem|
|
|
3
|
+
gem.name = "fluent-plugin-http-list"
|
|
4
|
+
gem.version = "0.1.0"
|
|
5
|
+
gem.authors = ["Paul McCann"]
|
|
6
|
+
gem.email = ["polm@dampfkraft.com"]
|
|
7
|
+
gem.description = %q{fluent plugin to accept multiple events in one HTTP request}
|
|
8
|
+
gem.summary = %q{fluent plugin to accept multiple events in one HTTP request}
|
|
9
|
+
gem.homepage = "https://github.com/m3dev/fluent-plugin-http-list"
|
|
10
|
+
|
|
11
|
+
gem.files = `git ls-files`.split($\)
|
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
|
13
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
|
14
|
+
gem.require_paths = ["lib"]
|
|
15
|
+
|
|
16
|
+
gem.add_development_dependency "fluentd"
|
|
17
|
+
gem.add_runtime_dependency "fluentd"
|
|
18
|
+
end
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
module Fluent
|
|
2
|
+
|
|
3
|
+
class HttpListInput < Input
|
|
4
|
+
Plugin.register_input('http_list', self)
|
|
5
|
+
|
|
6
|
+
include DetachMultiProcessMixin
|
|
7
|
+
|
|
8
|
+
require 'http/parser'
|
|
9
|
+
|
|
10
|
+
def initialize
|
|
11
|
+
require 'webrick/httputils'
|
|
12
|
+
super
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
config_param :port, :integer, :default => 9880
|
|
16
|
+
config_param :bind, :string, :default => '0.0.0.0'
|
|
17
|
+
config_param :body_size_limit, :size, :default => 32*1024*1024
|
|
18
|
+
config_param :keepalive_timeout, :time, :default => 10
|
|
19
|
+
|
|
20
|
+
def configure(conf)
|
|
21
|
+
super
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
class KeepaliveManager < Coolio::TimerWatcher
|
|
25
|
+
class TimerValue
|
|
26
|
+
def initialize
|
|
27
|
+
@value = 0
|
|
28
|
+
end
|
|
29
|
+
attr_accessor :value
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def initialize(timeout)
|
|
33
|
+
super(1, true)
|
|
34
|
+
@cons = {}
|
|
35
|
+
@timeout = timeout.to_i
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def add(sock)
|
|
39
|
+
@cons[sock] = sock
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def delete(sock)
|
|
43
|
+
@cons.delete(sock)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def on_timer
|
|
47
|
+
@cons.each_pair {|sock,val|
|
|
48
|
+
if sock.step_idle > @timeout
|
|
49
|
+
sock.close
|
|
50
|
+
end
|
|
51
|
+
}
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def start
|
|
56
|
+
$log.debug "listening for http on #{@bind}:#{@port}"
|
|
57
|
+
lsock = TCPServer.new(@bind, @port)
|
|
58
|
+
|
|
59
|
+
detach_multi_process do
|
|
60
|
+
super
|
|
61
|
+
@km = KeepaliveManager.new(@keepalive_timeout)
|
|
62
|
+
@lsock = Coolio::TCPServer.new(lsock, nil, Handler, @km, method(:on_request), @body_size_limit)
|
|
63
|
+
|
|
64
|
+
@loop = Coolio::Loop.new
|
|
65
|
+
@loop.attach(@km)
|
|
66
|
+
@loop.attach(@lsock)
|
|
67
|
+
|
|
68
|
+
@thread = Thread.new(&method(:run))
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def shutdown
|
|
73
|
+
@loop.watchers.each {|w| w.detach }
|
|
74
|
+
@loop.stop
|
|
75
|
+
@lsock.close
|
|
76
|
+
@thread.join
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def run
|
|
80
|
+
@loop.run
|
|
81
|
+
rescue
|
|
82
|
+
$log.error "unexpected error", :error=>$!.to_s
|
|
83
|
+
$log.error_backtrace
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def on_request(path_info, params)
|
|
87
|
+
begin
|
|
88
|
+
path = path_info[1..-1] # remove /
|
|
89
|
+
tag = path.split('/').join('.')
|
|
90
|
+
|
|
91
|
+
if js = params['json']
|
|
92
|
+
records = JSON.parse(js)
|
|
93
|
+
p records
|
|
94
|
+
else
|
|
95
|
+
raise "'json' parameter is required" + params.keys.to_s
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
time = params['time'].nil? ? Engine.now : params['time'].to_i
|
|
99
|
+
|
|
100
|
+
rescue
|
|
101
|
+
return ["400 Bad Request", {'Content-type'=>'text/plain'}, "400 Bad Request\n#{$!}\n"]
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
begin
|
|
106
|
+
records.each{|r|
|
|
107
|
+
Engine.emit(tag, time, r)
|
|
108
|
+
}
|
|
109
|
+
rescue
|
|
110
|
+
return ["500 Internal Server Error", {'Content-type'=>'text/plain'}, "500 Internal Server Error\n#{$!}\n"]
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
return ["200 OK", {'Content-type'=>'text/plain'}, ""]
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
class Handler < Coolio::Socket
|
|
117
|
+
def initialize(io, km, callback, body_size_limit)
|
|
118
|
+
super(io)
|
|
119
|
+
@km = km
|
|
120
|
+
@callback = callback
|
|
121
|
+
@body_size_limit = body_size_limit
|
|
122
|
+
@content_type = ""
|
|
123
|
+
@next_close = false
|
|
124
|
+
|
|
125
|
+
@idle = 0
|
|
126
|
+
@km.add(self)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def step_idle
|
|
130
|
+
@idle += 1
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def on_close
|
|
134
|
+
@km.delete(self)
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def on_connect
|
|
138
|
+
@parser = Http::Parser.new(self)
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def on_read(data)
|
|
142
|
+
@idle = 0
|
|
143
|
+
@parser << data
|
|
144
|
+
rescue
|
|
145
|
+
$log.warn "unexpected error", :error=>$!.to_s
|
|
146
|
+
$log.warn_backtrace
|
|
147
|
+
close
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def on_message_begin
|
|
151
|
+
@body = ''
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def on_headers_complete(headers)
|
|
155
|
+
expect = nil
|
|
156
|
+
size = nil
|
|
157
|
+
if @parser.http_version == [1, 1]
|
|
158
|
+
#Modified to always be false - Paul McCann 2012/10/24
|
|
159
|
+
#Changed because it was likely cause of slowness in production
|
|
160
|
+
@keep_alive = false
|
|
161
|
+
else
|
|
162
|
+
@keep_alive = false
|
|
163
|
+
end
|
|
164
|
+
headers.each_pair {|k,v|
|
|
165
|
+
case k
|
|
166
|
+
when /Expect/i
|
|
167
|
+
expect = v
|
|
168
|
+
when /Content-Length/i
|
|
169
|
+
size = v.to_i
|
|
170
|
+
when /Content-Type/i
|
|
171
|
+
@content_type = v
|
|
172
|
+
when /Connection/i
|
|
173
|
+
if v =~ /close/i
|
|
174
|
+
@keep_alive = false
|
|
175
|
+
elsif v =~ /Keep-alive/i
|
|
176
|
+
@keep_alive = true
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
}
|
|
180
|
+
if expect
|
|
181
|
+
if expect == '100-continue'
|
|
182
|
+
if !size || size < @body_size_limit
|
|
183
|
+
send_response_nobody("100 Continue", {})
|
|
184
|
+
else
|
|
185
|
+
send_response_and_close("413 Request Entity Too Large", {}, "Too large")
|
|
186
|
+
end
|
|
187
|
+
else
|
|
188
|
+
send_response_and_close("417 Expectation Failed", {}, "")
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
def on_body(chunk)
|
|
194
|
+
if @body.bytesize + chunk.bytesize > @body_size_limit
|
|
195
|
+
unless closing?
|
|
196
|
+
send_response_and_close("413 Request Entity Too Large", {}, "Too large")
|
|
197
|
+
end
|
|
198
|
+
return
|
|
199
|
+
end
|
|
200
|
+
@body << chunk
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
def on_message_complete
|
|
204
|
+
return if closing?
|
|
205
|
+
|
|
206
|
+
params = WEBrick::HTTPUtils.parse_query(@parser.query_string)
|
|
207
|
+
|
|
208
|
+
if @content_type =~ /^application\/x-www-form-urlencoded/
|
|
209
|
+
params.update WEBrick::HTTPUtils.parse_query(@body)
|
|
210
|
+
elsif @content_type =~ /^multipart\/form-data; boundary=(.+)/
|
|
211
|
+
boundary = WEBrick::HTTPUtils.dequote($1)
|
|
212
|
+
params.update WEBrick::HTTPUtils.parse_form_data(@body, boundary)
|
|
213
|
+
elsif @content_type =~ /^application\/json/
|
|
214
|
+
params['json'] = @body
|
|
215
|
+
end
|
|
216
|
+
path_info = @parser.request_path
|
|
217
|
+
|
|
218
|
+
code, header, body = *@callback.call(path_info, params)
|
|
219
|
+
body = body.to_s
|
|
220
|
+
|
|
221
|
+
if @keep_alive
|
|
222
|
+
header['Connection'] = 'Keep-Alive'
|
|
223
|
+
send_response(code, header, body)
|
|
224
|
+
else
|
|
225
|
+
send_response_and_close(code, header, body)
|
|
226
|
+
end
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
def on_write_complete
|
|
230
|
+
close if @next_close
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
def send_response_and_close(code, header, body)
|
|
234
|
+
send_response(code, header, body)
|
|
235
|
+
@next_close = true
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
def closing?
|
|
239
|
+
@next_close
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
def send_response(code, header, body)
|
|
243
|
+
header['Content-length'] ||= body.bytesize
|
|
244
|
+
header['Content-type'] ||= 'text/plain'
|
|
245
|
+
|
|
246
|
+
data = %[HTTP/1.1 #{code}\r\n]
|
|
247
|
+
header.each_pair {|k,v|
|
|
248
|
+
data << "#{k}: #{v}\r\n"
|
|
249
|
+
}
|
|
250
|
+
data << "\r\n"
|
|
251
|
+
write data
|
|
252
|
+
|
|
253
|
+
write body
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
def send_response_nobody(code, header)
|
|
257
|
+
data = %[HTTP/1.1 #{code}\r\n]
|
|
258
|
+
header.each_pair {|k,v|
|
|
259
|
+
data << "#{k}: #{v}\r\n"
|
|
260
|
+
}
|
|
261
|
+
data << "\r\n"
|
|
262
|
+
write data
|
|
263
|
+
end
|
|
264
|
+
end
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
end
|
|
269
|
+
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
require 'fluent/test'
|
|
2
|
+
require 'net/http'
|
|
3
|
+
|
|
4
|
+
class HttpListInputTest < Test::Unit::TestCase
|
|
5
|
+
def setup
|
|
6
|
+
Fluent::Test.setup
|
|
7
|
+
require 'fluent/plugin/in_http_list'
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
CONFIG = %[
|
|
11
|
+
port 9911
|
|
12
|
+
bind 127.0.0.1
|
|
13
|
+
body_size_limit 10m
|
|
14
|
+
keepalive_timeout 5
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
def create_driver(conf=CONFIG)
|
|
18
|
+
Fluent::Test::InputTestDriver.new(Fluent::HttpListInput).configure(conf)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def test_configure
|
|
22
|
+
d = create_driver
|
|
23
|
+
assert_equal 9911, d.instance.port
|
|
24
|
+
assert_equal '127.0.0.1', d.instance.bind
|
|
25
|
+
assert_equal 10*1024*1024, d.instance.body_size_limit
|
|
26
|
+
assert_equal 5, d.instance.keepalive_timeout
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
#
|
|
30
|
+
# sending events as a post parameter named 'json'
|
|
31
|
+
# e.g. curl -XPOST 'http://127.0.0.1:9911/tag1' -d'time=1357860203&json=[{"a":1}]'
|
|
32
|
+
#
|
|
33
|
+
def test_parameter
|
|
34
|
+
d = create_driver
|
|
35
|
+
|
|
36
|
+
time = Time.parse("2013-01-10 23:23:23 UTC").to_i
|
|
37
|
+
|
|
38
|
+
d.expect_emit "tag1", time, {"a"=>1}
|
|
39
|
+
d.expect_emit "tag2", time, {"a"=>2}
|
|
40
|
+
|
|
41
|
+
d.run do
|
|
42
|
+
d.expected_emits.each {|tag,time,record|
|
|
43
|
+
res = post_as_parameter("/#{tag}", time.to_s, [record].to_json)
|
|
44
|
+
assert_equal "200", res.code
|
|
45
|
+
}
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
#
|
|
50
|
+
# sending evens as a request body (application/json)
|
|
51
|
+
# e.g. curl -XPOST 'http://127.0.0.1:9911/tag1?time=1357860203' -d'[{"a":1}]' -H 'Content-Type:application/json; charset=utf-8'
|
|
52
|
+
#
|
|
53
|
+
def test_application_json
|
|
54
|
+
d = create_driver
|
|
55
|
+
|
|
56
|
+
time = Time.parse("2013-01-10 23:23:23 UTC").to_i
|
|
57
|
+
|
|
58
|
+
d.expect_emit "tag1", time, {"a"=>1}
|
|
59
|
+
d.expect_emit "tag2", time, {"a"=>2}
|
|
60
|
+
|
|
61
|
+
d.run do
|
|
62
|
+
d.expected_emits.each {|tag,time,record|
|
|
63
|
+
res = post_as_application_json("/#{tag}", time.to_s, [record].to_json)
|
|
64
|
+
assert_equal "200", res.code
|
|
65
|
+
}
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def test_multiple_events_as_parameter
|
|
70
|
+
d = create_driver
|
|
71
|
+
|
|
72
|
+
time = Time.parse("2013-01-10 23:23:23 UTC").to_i
|
|
73
|
+
|
|
74
|
+
d.expect_emit "tag1", time, {"a"=>1}
|
|
75
|
+
d.expect_emit "tag1", time, {"a"=>2}
|
|
76
|
+
d.expect_emit "tag1", time, {"a"=>3}
|
|
77
|
+
d.expect_emit "tag2", time, {"a"=>4}
|
|
78
|
+
d.expect_emit "tag2", time, {"a"=>5}
|
|
79
|
+
d.expect_emit "tag2", time, {"a"=>6}
|
|
80
|
+
|
|
81
|
+
test_events = [
|
|
82
|
+
["tag1", (1..3).to_a.collect {|x| {"a"=>x}}],
|
|
83
|
+
["tag2", (4..6).to_a.collect {|x| {"a"=>x}}]
|
|
84
|
+
]
|
|
85
|
+
|
|
86
|
+
d.run do
|
|
87
|
+
test_events.each {|tag, events|
|
|
88
|
+
res = post_as_parameter("/#{tag}", time, events.to_json)
|
|
89
|
+
assert_equal "200", res.code
|
|
90
|
+
}
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def test_multiple_events_as_application_json
|
|
95
|
+
d = create_driver
|
|
96
|
+
|
|
97
|
+
time = Time.parse("2013-01-10 23:23:23 UTC").to_i
|
|
98
|
+
|
|
99
|
+
d.expect_emit "tag1", time, {"a"=>1}
|
|
100
|
+
d.expect_emit "tag1", time, {"a"=>2}
|
|
101
|
+
d.expect_emit "tag1", time, {"a"=>3}
|
|
102
|
+
d.expect_emit "tag2", time, {"a"=>4}
|
|
103
|
+
d.expect_emit "tag2", time, {"a"=>5}
|
|
104
|
+
d.expect_emit "tag2", time, {"a"=>6}
|
|
105
|
+
|
|
106
|
+
test_events = [
|
|
107
|
+
["tag1", (1..3).to_a.collect {|x| {"a"=>x}}],
|
|
108
|
+
["tag2", (4..6).to_a.collect {|x| {"a"=>x}}]
|
|
109
|
+
]
|
|
110
|
+
|
|
111
|
+
d.run do
|
|
112
|
+
test_events.each {|tag, events|
|
|
113
|
+
res = post_as_application_json("/#{tag}", time.to_s, events.to_json)
|
|
114
|
+
assert_equal "200", res.code
|
|
115
|
+
}
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def test_zero_events_as_parameter
|
|
120
|
+
# An empty event list should not fail
|
|
121
|
+
d = create_driver
|
|
122
|
+
time = Time.parse("2013-01-10 23:23:23 UTC").to_i
|
|
123
|
+
d.run do
|
|
124
|
+
res = post_as_parameter("/zero", time.to_s, [].to_json)
|
|
125
|
+
assert_equal "200", res.code
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def test_zero_events_as_application_json
|
|
130
|
+
# An empty event list should not fail
|
|
131
|
+
d = create_driver
|
|
132
|
+
time = Time.parse("2013-01-10 23:23:23 UTC").to_i
|
|
133
|
+
d.run do
|
|
134
|
+
res = post_as_application_json("/zero", time.to_s, [].to_json)
|
|
135
|
+
assert_equal "200", res.code
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
private
|
|
140
|
+
|
|
141
|
+
def post_as_parameter(path, time, json)
|
|
142
|
+
http = Net::HTTP.new("127.0.0.1", 9911)
|
|
143
|
+
req = Net::HTTP::Post.new(path, {})
|
|
144
|
+
req.set_form_data({"time" => time, "json" => json})
|
|
145
|
+
http.request(req)
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def post_as_application_json(path, time, json)
|
|
149
|
+
http = Net::HTTP.new("127.0.0.1", 9911)
|
|
150
|
+
req = Net::HTTP::Post.new("#{path}?time=#{time.to_s}", {"content-type"=>"application/json; charset=utf-8"})
|
|
151
|
+
req.body = json
|
|
152
|
+
http.request(req)
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
end
|
|
156
|
+
|
metadata
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: fluent-plugin-http-list
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
prerelease:
|
|
6
|
+
platform: ruby
|
|
7
|
+
authors:
|
|
8
|
+
- Paul McCann
|
|
9
|
+
autorequire:
|
|
10
|
+
bindir: bin
|
|
11
|
+
cert_chain: []
|
|
12
|
+
date: 2013-01-16 00:00:00.000000000 Z
|
|
13
|
+
dependencies:
|
|
14
|
+
- !ruby/object:Gem::Dependency
|
|
15
|
+
name: fluentd
|
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
|
17
|
+
none: false
|
|
18
|
+
requirements:
|
|
19
|
+
- - ! '>='
|
|
20
|
+
- !ruby/object:Gem::Version
|
|
21
|
+
version: '0'
|
|
22
|
+
type: :development
|
|
23
|
+
prerelease: false
|
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
25
|
+
none: false
|
|
26
|
+
requirements:
|
|
27
|
+
- - ! '>='
|
|
28
|
+
- !ruby/object:Gem::Version
|
|
29
|
+
version: '0'
|
|
30
|
+
- !ruby/object:Gem::Dependency
|
|
31
|
+
name: fluentd
|
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
|
33
|
+
none: false
|
|
34
|
+
requirements:
|
|
35
|
+
- - ! '>='
|
|
36
|
+
- !ruby/object:Gem::Version
|
|
37
|
+
version: '0'
|
|
38
|
+
type: :runtime
|
|
39
|
+
prerelease: false
|
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
41
|
+
none: false
|
|
42
|
+
requirements:
|
|
43
|
+
- - ! '>='
|
|
44
|
+
- !ruby/object:Gem::Version
|
|
45
|
+
version: '0'
|
|
46
|
+
description: fluent plugin to accept multiple events in one HTTP request
|
|
47
|
+
email:
|
|
48
|
+
- polm@dampfkraft.com
|
|
49
|
+
executables: []
|
|
50
|
+
extensions: []
|
|
51
|
+
extra_rdoc_files: []
|
|
52
|
+
files:
|
|
53
|
+
- .gitignore
|
|
54
|
+
- Gemfile
|
|
55
|
+
- LICENSE
|
|
56
|
+
- README.md
|
|
57
|
+
- Rakefile
|
|
58
|
+
- fluent-plugin-http-list.gemspec
|
|
59
|
+
- lib/fluent/plugin/in_http_list.rb
|
|
60
|
+
- test/plugin/test_in_http_list.rb
|
|
61
|
+
homepage: https://github.com/m3dev/fluent-plugin-http-list
|
|
62
|
+
licenses: []
|
|
63
|
+
post_install_message:
|
|
64
|
+
rdoc_options: []
|
|
65
|
+
require_paths:
|
|
66
|
+
- lib
|
|
67
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
68
|
+
none: false
|
|
69
|
+
requirements:
|
|
70
|
+
- - ! '>='
|
|
71
|
+
- !ruby/object:Gem::Version
|
|
72
|
+
version: '0'
|
|
73
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
74
|
+
none: false
|
|
75
|
+
requirements:
|
|
76
|
+
- - ! '>='
|
|
77
|
+
- !ruby/object:Gem::Version
|
|
78
|
+
version: '0'
|
|
79
|
+
requirements: []
|
|
80
|
+
rubyforge_project:
|
|
81
|
+
rubygems_version: 1.8.24
|
|
82
|
+
signing_key:
|
|
83
|
+
specification_version: 3
|
|
84
|
+
summary: fluent plugin to accept multiple events in one HTTP request
|
|
85
|
+
test_files:
|
|
86
|
+
- test/plugin/test_in_http_list.rb
|