fluent-plugin-https-client 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/README.md +44 -0
- data/fluent-plugin-https-client.gemspec +20 -0
- data/lib/fluent/plugin/out_https_client.rb +174 -0
- metadata +76 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 3b59b6107b871dd3b8d36e7df137961cd9f1a68e
|
4
|
+
data.tar.gz: 63f34236d611c5e7968e298a696a2d934b66aa88
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 3da69d57d183d3fac60a0f40e0388633c2efe78ffa525d6651e58dba39ac65a5c7724fc6b20f34346df1889e5fb1712465fdd2e60f86a37ca9d971369eafa1c6
|
7
|
+
data.tar.gz: 745b017399dc6383bc9669953cf9d0a5964926ef27fcb9414226f8fbd83280523d165e5d7705d5c9c5d31cba408f631286c4d237c80deccdbeaf9c9c528682cc
|
data/README.md
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
## Fluent::Plugin::HTTPSClient
|
2
|
+
|
3
|
+
Output plugin for [Fluentd](http://fluentd.org), for sending records to an HTTP or HTTPS endpoint, with SSL, Proxy,
|
4
|
+
and Header implementation.
|
5
|
+
|
6
|
+
## Configuration Guide
|
7
|
+
|
8
|
+
<match *>
|
9
|
+
type https_client
|
10
|
+
endpoint_url # endpoint_url
|
11
|
+
http_method # get / post / put / delete defaults to post
|
12
|
+
serializer # json / form defaults to form
|
13
|
+
include_timestamp # true / false defaults to false
|
14
|
+
rate_limit_msec # limit the rate in ms, defaults to 10 ms
|
15
|
+
auth # basic / none
|
16
|
+
use_ssl # true / false
|
17
|
+
proxy_addr # proxy url
|
18
|
+
proxy_port # proxy port
|
19
|
+
username # user name if auth is basic
|
20
|
+
password # password if auth is basic
|
21
|
+
<header> # HTTP headers (see examples below)
|
22
|
+
Accept application/json
|
23
|
+
auth_token my_secret
|
24
|
+
</header>
|
25
|
+
</match>
|
26
|
+
|
27
|
+
|
28
|
+
### Use Cases
|
29
|
+
* send records to HTTP endpoints
|
30
|
+
* send records to HTTPS endpoints
|
31
|
+
* send events through proxy
|
32
|
+
* send events by setting custom headers (header-based authentication, etc)
|
33
|
+
|
34
|
+
|
35
|
+
### Credits
|
36
|
+
* Majority of the code is cloned from [fluent-plugin-out-http][2]
|
37
|
+
* SSL implementation from [fluent-plugin-out-https][3]
|
38
|
+
|
39
|
+
### Exception Handling
|
40
|
+
* For retries in case of exceptions, use
|
41
|
+
[fluent-plugin-bufferize](https://github.com/kazegusuri/fluent-plugin-bufferize) as a wrapper.
|
42
|
+
|
43
|
+
|
44
|
+
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |gem|
|
4
|
+
gem.name = 'fluent-plugin-https-client'
|
5
|
+
gem.version = '0.0.1'
|
6
|
+
gem.authors = ['Arash Vatanpoor']
|
7
|
+
gem.email = ['arash@a-venture.org']
|
8
|
+
gem.summary = %q{A generic Fluentd output plugin to send records to HTTP / HTTPS endpoint}
|
9
|
+
gem.description = %q{A generic Fluentd output plugin to send records to HTTP / HTTPS endpoint, with SSL, Proxy, and Header implementation}
|
10
|
+
gem.homepage = 'https://github.com/a-venture/fluent-plugin-https-client'
|
11
|
+
gem.license = 'MIT'
|
12
|
+
gem.files = `git ls-files`.split($\)
|
13
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
14
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
15
|
+
gem.require_paths = ['lib']
|
16
|
+
gem.required_ruby_version = '>= 2.1.2'
|
17
|
+
|
18
|
+
gem.add_runtime_dependency 'yajl-ruby', '~> 1.0'
|
19
|
+
gem.add_runtime_dependency 'fluentd', '~> 0.12'
|
20
|
+
end
|
@@ -0,0 +1,174 @@
|
|
1
|
+
class Fluent::HTTPSOutput < Fluent::Output
|
2
|
+
Fluent::Plugin.register_output('https_client', self)
|
3
|
+
|
4
|
+
def initialize
|
5
|
+
super
|
6
|
+
require 'net/https'
|
7
|
+
require 'openssl'
|
8
|
+
require 'uri'
|
9
|
+
require 'yajl'
|
10
|
+
end
|
11
|
+
|
12
|
+
config_param :use_ssl, :bool, :default => false
|
13
|
+
config_param :include_tag, :bool, :default => false
|
14
|
+
config_param :include_timestamp, :bool, :default => false
|
15
|
+
config_param :endpoint_url, :string
|
16
|
+
config_param :http_method, :string, :default => :post
|
17
|
+
config_param :serializer, :string, :default => :form
|
18
|
+
config_param :rate_limit_msec, :integer, :default => 10
|
19
|
+
config_param :auth, :string, :default => nil
|
20
|
+
config_param :username, :string, :default => ''
|
21
|
+
config_param :password, :string, :default => ''
|
22
|
+
config_param :proxy_addr, :string, :default => ''
|
23
|
+
config_param :proxy_port, :integer, :default => -1
|
24
|
+
|
25
|
+
|
26
|
+
|
27
|
+
def configure(conf)
|
28
|
+
super
|
29
|
+
|
30
|
+
@use_ssl = conf['use_ssl']
|
31
|
+
@include_tag = conf['include_tag']
|
32
|
+
@include_timestamp = conf['include_timestamp']
|
33
|
+
|
34
|
+
|
35
|
+
@use_proxy = false
|
36
|
+
if @proxy_port and @proxy_addr
|
37
|
+
# check for proxy settings
|
38
|
+
if @proxy_port > 0 and @proxy_addr.empty?
|
39
|
+
raise Fluent::ConfigError, 'HTTPS Output :: provide a valid proxy address'
|
40
|
+
elsif @proxy_port <= 0 and !@proxy_addr.empty?
|
41
|
+
raise Fluent::ConfigError, 'HTTPS Output :: provide a valid proxy port number'
|
42
|
+
elsif @proxy_port == 0
|
43
|
+
raise Fluent::ConfigError, 'HTTPS Output :: provide a valid proxy port number'
|
44
|
+
elsif @proxy_port > 0 and !@proxy_addr.empty?
|
45
|
+
@use_proxy = true
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
serializers = [:json, :form]
|
50
|
+
@serializer = if serializers.include? @serializer.intern
|
51
|
+
@serializer.intern
|
52
|
+
else
|
53
|
+
:form
|
54
|
+
end
|
55
|
+
|
56
|
+
http_methods = [:get, :put, :post, :delete]
|
57
|
+
@http_method = if http_methods.include? @http_method.intern
|
58
|
+
@http_method.intern
|
59
|
+
else
|
60
|
+
:post
|
61
|
+
end
|
62
|
+
|
63
|
+
@auth = case @auth
|
64
|
+
when 'basic' then :basic
|
65
|
+
else
|
66
|
+
:none
|
67
|
+
end
|
68
|
+
|
69
|
+
# create the headers hash
|
70
|
+
@headers = {}
|
71
|
+
conf.elements.each do |elem|
|
72
|
+
elem.keys.each do |key|
|
73
|
+
@headers[key] = elem[key]
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def start
|
79
|
+
super
|
80
|
+
end
|
81
|
+
|
82
|
+
def shutdown
|
83
|
+
super
|
84
|
+
end
|
85
|
+
|
86
|
+
def format_url
|
87
|
+
@endpoint_url
|
88
|
+
end
|
89
|
+
|
90
|
+
def set_body(req, tag, record)
|
91
|
+
if @include_tag
|
92
|
+
record['tag'] = tag
|
93
|
+
end
|
94
|
+
if @include_timestamp
|
95
|
+
record['timestamp'] = Time.now.to_i
|
96
|
+
end
|
97
|
+
if @serializer == :json
|
98
|
+
set_json_body(req, record)
|
99
|
+
else
|
100
|
+
req.set_form_data(record)
|
101
|
+
end
|
102
|
+
req
|
103
|
+
end
|
104
|
+
|
105
|
+
def set_header(req)
|
106
|
+
@headers.each do |key, value|
|
107
|
+
req[key] = value
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def set_json_body(req, data)
|
112
|
+
req.body = Yajl.dump(data)
|
113
|
+
req['Content-Type'] = 'application/json'
|
114
|
+
end
|
115
|
+
|
116
|
+
def create_request(tag, time, record)
|
117
|
+
url = format_url()
|
118
|
+
uri = URI.parse(url)
|
119
|
+
req = Net::HTTP.const_get(@http_method.to_s.capitalize).new(uri.path)
|
120
|
+
set_body(req, tag, record)
|
121
|
+
set_header(req)
|
122
|
+
return req, uri
|
123
|
+
end
|
124
|
+
|
125
|
+
def send_request(req, uri, record)
|
126
|
+
is_rate_limited = (@rate_limit_msec != 0 and not @last_request_time.nil?)
|
127
|
+
if is_rate_limited and ((Time.now.to_f - @last_request_time) * 1000.0 < @rate_limit_msec)
|
128
|
+
$log.info('Dropped request due to rate limiting')
|
129
|
+
return
|
130
|
+
end
|
131
|
+
|
132
|
+
res = nil
|
133
|
+
begin
|
134
|
+
if @auth and @auth == :basic
|
135
|
+
req.basic_auth(@username, @password)
|
136
|
+
end
|
137
|
+
@last_request_time = Time.now.to_f
|
138
|
+
if @use_proxy
|
139
|
+
https = Net::HTTP.new(uri.host, uri.port, @proxy_addr, @proxy_port)
|
140
|
+
else
|
141
|
+
https = Net::HTTP.new(uri.host, uri.port)
|
142
|
+
end
|
143
|
+
https.use_ssl = @use_ssl
|
144
|
+
https.ca_file = OpenSSL::X509::DEFAULT_CERT_FILE
|
145
|
+
https.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
146
|
+
res = https.start {|http| http.request(req) }
|
147
|
+
rescue IOError, EOFError, SystemCallError
|
148
|
+
$log.warn "HTTPS Output :: Net::HTTP.#{req.method.capitalize} raises exception: #{$!.class}, '#{$!.message}'"
|
149
|
+
end
|
150
|
+
unless res and res.is_a?(Net::HTTPSuccess)
|
151
|
+
res_summary = if res
|
152
|
+
"#{res.code} #{res.message} #{res.body}"
|
153
|
+
else
|
154
|
+
"res=nil"
|
155
|
+
end
|
156
|
+
$log.warn "HTTPS Output :: failed to #{req.method} #{uri} (#{res_summary})"
|
157
|
+
$log.warn "HTTPS Output :: record failed to send : #{record}"
|
158
|
+
else
|
159
|
+
$log.info "HTTPS Output :: emitted record : #{record}"
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def handle_record(tag, time, record)
|
164
|
+
req, uri = create_request(tag, time, record)
|
165
|
+
send_request(req, uri, record)
|
166
|
+
end
|
167
|
+
|
168
|
+
def emit(tag, es, chain)
|
169
|
+
es.each do |time, record|
|
170
|
+
handle_record(tag, time, record)
|
171
|
+
end
|
172
|
+
chain.next
|
173
|
+
end
|
174
|
+
end
|
metadata
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: fluent-plugin-https-client
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Arash Vatanpoor
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-08-15 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: yajl-ruby
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: fluentd
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.12'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.12'
|
41
|
+
description: A generic Fluentd output plugin to send records to HTTP / HTTPS endpoint,
|
42
|
+
with SSL, Proxy, and Header implementation
|
43
|
+
email:
|
44
|
+
- arash@a-venture.org
|
45
|
+
executables: []
|
46
|
+
extensions: []
|
47
|
+
extra_rdoc_files: []
|
48
|
+
files:
|
49
|
+
- README.md
|
50
|
+
- fluent-plugin-https-client.gemspec
|
51
|
+
- lib/fluent/plugin/out_https_client.rb
|
52
|
+
homepage: https://github.com/a-venture/fluent-plugin-https-client
|
53
|
+
licenses:
|
54
|
+
- MIT
|
55
|
+
metadata: {}
|
56
|
+
post_install_message:
|
57
|
+
rdoc_options: []
|
58
|
+
require_paths:
|
59
|
+
- lib
|
60
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
61
|
+
requirements:
|
62
|
+
- - ">="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: 2.1.2
|
65
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
requirements: []
|
71
|
+
rubyforge_project:
|
72
|
+
rubygems_version: 2.6.8
|
73
|
+
signing_key:
|
74
|
+
specification_version: 4
|
75
|
+
summary: A generic Fluentd output plugin to send records to HTTP / HTTPS endpoint
|
76
|
+
test_files: []
|