logstash-input-http 3.1.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 +7 -0
- data/CHANGELOG.md +60 -0
- data/DEVELOPER.md +1 -0
- data/Gemfile +11 -0
- data/LICENSE +13 -0
- data/NOTICE.TXT +5 -0
- data/README.md +98 -0
- data/VERSION +1 -0
- data/docs/index.asciidoc +309 -0
- data/lib/logstash-input-http_jars.rb +7 -0
- data/lib/logstash/inputs/http.rb +290 -0
- data/lib/logstash/inputs/http/message_handler.rb +62 -0
- data/lib/logstash/inputs/http/tls.rb +40 -0
- data/lib/logstash/util/http_compressed_requests.rb +39 -0
- data/lib/tasks/build.rake +16 -0
- data/logstash-input-http.gemspec +33 -0
- data/spec/inputs/http_spec.rb +277 -0
- data/vendor/jar-dependencies/io/netty/netty-all/4.1.18.Final/netty-all-4.1.18.Final.jar +0 -0
- data/vendor/jar-dependencies/io/netty/netty-tcnative-boringssl-static/2.0.7.Final/netty-tcnative-boringssl-static-2.0.7.Final.jar +0 -0
- data/vendor/jar-dependencies/org/apache/logging/log4j/log4j-api/2.6.2/log4j-api-2.6.2.jar +0 -0
- data/vendor/jar-dependencies/org/logstash/plugins/input/http/logstash-input-http/3.1.0/logstash-input-http-3.1.0.jar +0 -0
- metadata +173 -0
@@ -0,0 +1,7 @@
|
|
1
|
+
# AUTOGENERATED BY THE GRADLE SCRIPT. DO NOT EDIT.
|
2
|
+
|
3
|
+
require 'jar_dependencies'
|
4
|
+
require_jar('io.netty', 'netty-all', '4.1.18.Final')
|
5
|
+
require_jar('io.netty', 'netty-tcnative-boringssl-static', '2.0.7.Final')
|
6
|
+
require_jar('org.apache.logging.log4j', 'log4j-api', '2.6.2')
|
7
|
+
require_jar('org.logstash.plugins.input.http', 'logstash-input-http', '3.1.0')
|
@@ -0,0 +1,290 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "logstash/inputs/base"
|
3
|
+
require "logstash/namespace"
|
4
|
+
require "stud/interval"
|
5
|
+
require "logstash-input-http_jars"
|
6
|
+
|
7
|
+
# Using this input you can receive single or multiline events over http(s).
|
8
|
+
# Applications can send a HTTP POST request with a body to the endpoint started by this
|
9
|
+
# input and Logstash will convert it into an event for subsequent processing. Users
|
10
|
+
# can pass plain text, JSON, or any formatted data and use a corresponding codec with this
|
11
|
+
# input. For Content-Type `application/json` the `json` codec is used, but for all other
|
12
|
+
# data formats, `plain` codec is used.
|
13
|
+
#
|
14
|
+
# This input can also be used to receive webhook requests to integrate with other services
|
15
|
+
# and applications. By taking advantage of the vast plugin ecosystem available in Logstash
|
16
|
+
# you can trigger actionable events right from your application.
|
17
|
+
#
|
18
|
+
# ==== Security
|
19
|
+
# This plugin supports standard HTTP basic authentication headers to identify the requester.
|
20
|
+
# You can pass in an username, password combination while sending data to this input
|
21
|
+
#
|
22
|
+
# You can also setup SSL and send data securely over https, with an option of validating
|
23
|
+
# the client's certificate. Currently, the certificate setup is through
|
24
|
+
# https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html[Java Keystore
|
25
|
+
# format]
|
26
|
+
#
|
27
|
+
class LogStash::Inputs::Http < LogStash::Inputs::Base
|
28
|
+
require "logstash/inputs/http/tls"
|
29
|
+
|
30
|
+
config_name "http"
|
31
|
+
|
32
|
+
# Codec used to decode the incoming data.
|
33
|
+
# This codec will be used as a fall-back if the content-type
|
34
|
+
# is not found in the "additional_codecs" hash
|
35
|
+
default :codec, "plain"
|
36
|
+
|
37
|
+
# The host or ip to bind
|
38
|
+
config :host, :validate => :string, :default => "0.0.0.0"
|
39
|
+
|
40
|
+
# The TCP port to bind to
|
41
|
+
config :port, :validate => :number, :default => 8080
|
42
|
+
|
43
|
+
# Username for basic authorization
|
44
|
+
config :user, :validate => :string, :required => false
|
45
|
+
|
46
|
+
# Password for basic authorization
|
47
|
+
config :password, :validate => :password, :required => false
|
48
|
+
|
49
|
+
# Events are by default sent in plain text. You can
|
50
|
+
# enable encryption by setting `ssl` to true and configuring
|
51
|
+
# the `ssl_certificate` and `ssl_key` options.
|
52
|
+
config :ssl, :validate => :boolean, :default => false
|
53
|
+
|
54
|
+
# SSL certificate to use.
|
55
|
+
config :ssl_certificate, :validate => :path
|
56
|
+
|
57
|
+
# SSL key to use.
|
58
|
+
# NOTE: This key need to be in the PKCS8 format, you can convert it with https://www.openssl.org/docs/man1.1.0/apps/pkcs8.html[OpenSSL]
|
59
|
+
# for more information.
|
60
|
+
config :ssl_key, :validate => :path
|
61
|
+
|
62
|
+
# SSL key passphrase to use.
|
63
|
+
config :ssl_key_passphrase, :validate => :password
|
64
|
+
|
65
|
+
# Validate client certificates against these authorities.
|
66
|
+
# You can define multiple files or paths. All the certificates will
|
67
|
+
# be read and added to the trust store. You need to configure the `ssl_verify_mode`
|
68
|
+
# to `peer` or `force_peer` to enable the verification.
|
69
|
+
config :ssl_certificate_authorities, :validate => :array, :default => []
|
70
|
+
|
71
|
+
# By default the server doesn't do any client verification.
|
72
|
+
#
|
73
|
+
# `peer` will make the server ask the client to provide a certificate.
|
74
|
+
# If the client provides a certificate, it will be validated.
|
75
|
+
#
|
76
|
+
# `force_peer` will make the server ask the client to provide a certificate.
|
77
|
+
# If the client doesn't provide a certificate, the connection will be closed.
|
78
|
+
#
|
79
|
+
# This option needs to be used with `ssl_certificate_authorities` and a defined list of CAs.
|
80
|
+
config :ssl_verify_mode, :validate => ["none", "peer", "force_peer"], :default => "none"
|
81
|
+
|
82
|
+
# Time in milliseconds for an incomplete ssl handshake to timeout
|
83
|
+
config :ssl_handshake_timeout, :validate => :number, :default => 10000
|
84
|
+
|
85
|
+
# The minimum TLS version allowed for the encrypted connections. The value must be one of the following:
|
86
|
+
# 1.0 for TLS 1.0, 1.1 for TLS 1.1, 1.2 for TLS 1.2
|
87
|
+
config :tls_min_version, :validate => :number, :default => TLS.min.version
|
88
|
+
|
89
|
+
# The maximum TLS version allowed for the encrypted connections. The value must be the one of the following:
|
90
|
+
# 1.0 for TLS 1.0, 1.1 for TLS 1.1, 1.2 for TLS 1.2
|
91
|
+
config :tls_max_version, :validate => :number, :default => TLS.max.version
|
92
|
+
|
93
|
+
# The list of ciphers suite to use, listed by priorities.
|
94
|
+
config :cipher_suites, :validate => :array, :default => org.logstash.plugins.inputs.http.util.SslSimpleBuilder::DEFAULT_CIPHERS
|
95
|
+
|
96
|
+
# Apply specific codecs for specific content types.
|
97
|
+
# The default codec will be applied only after this list is checked
|
98
|
+
# and no codec for the request's content-type is found
|
99
|
+
config :additional_codecs, :validate => :hash, :default => { "application/json" => "json" }
|
100
|
+
|
101
|
+
# specify a custom set of response headers
|
102
|
+
config :response_headers, :validate => :hash, :default => { 'Content-Type' => 'text/plain' }
|
103
|
+
|
104
|
+
config :threads, :validate => :number, :required => false, :default => ::LogStash::Config::CpuCoreStrategy.maximum
|
105
|
+
|
106
|
+
config :max_pending_requests, :validate => :number, :required => false, :default => 200
|
107
|
+
|
108
|
+
config :max_content_length, :validate => :number, :required => false, :default => 100 * 1024 * 1024
|
109
|
+
|
110
|
+
# Deprecated options
|
111
|
+
|
112
|
+
# The JKS keystore to validate the client's certificates
|
113
|
+
config :keystore, :validate => :path, :deprecated => "Set 'ssl_certificate' and 'ssl_key' instead."
|
114
|
+
config :keystore_password, :validate => :password, :deprecated => "Set 'ssl_key_passphrase' instead."
|
115
|
+
|
116
|
+
config :verify_mode, :validate => ['none', 'peer', 'force_peer'], :default => 'none',
|
117
|
+
:deprecated => "Set 'ssl_verify_mode' instead."
|
118
|
+
|
119
|
+
public
|
120
|
+
def register
|
121
|
+
|
122
|
+
validate_ssl_settings!
|
123
|
+
|
124
|
+
if @user && @password then
|
125
|
+
token = Base64.strict_encode64("#{@user}:#{@password.value}")
|
126
|
+
@auth_token = "Basic #{token}"
|
127
|
+
end
|
128
|
+
|
129
|
+
@codecs = Hash.new
|
130
|
+
|
131
|
+
@additional_codecs.each do |content_type, codec|
|
132
|
+
@codecs[content_type] = LogStash::Plugin.lookup("codec", codec).new
|
133
|
+
end
|
134
|
+
|
135
|
+
require "logstash/inputs/http/message_handler"
|
136
|
+
message_handler = MessageHandler.new(self, @codec, @codecs)
|
137
|
+
@http_server = create_http_server(message_handler)
|
138
|
+
end # def register
|
139
|
+
|
140
|
+
def run(queue)
|
141
|
+
@queue = queue
|
142
|
+
@logger.info("Starting http input listener", :address => "#{@host}:#{@port}", :ssl => "#{@ssl}")
|
143
|
+
@http_server.run()
|
144
|
+
end
|
145
|
+
|
146
|
+
def stop
|
147
|
+
@http_server.close() rescue nil
|
148
|
+
end
|
149
|
+
|
150
|
+
def close
|
151
|
+
@http_server.close() rescue nil
|
152
|
+
end
|
153
|
+
|
154
|
+
def decode_body(remote_address, http_full_request, default_codec, additional_codecs)
|
155
|
+
body = read_bytes(http_full_request.content)
|
156
|
+
headers = {}
|
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)
|
168
|
+
codec.decode(body) { |event| push_decoded_event(headers, remote_address, event) }
|
169
|
+
codec.flush { |event| push_decoded_event(headers, remote_address, event) }
|
170
|
+
[200, @response_headers, 'ok']
|
171
|
+
rescue => e
|
172
|
+
@logger.error(
|
173
|
+
"unable to process event.",
|
174
|
+
:message => e.message,
|
175
|
+
:class => e.class.name,
|
176
|
+
:backtrace => e.backtrace
|
177
|
+
)
|
178
|
+
[500, @response_headers, 'internal error']
|
179
|
+
end
|
180
|
+
|
181
|
+
def push_decoded_event(headers, remote_address, event)
|
182
|
+
event.set("headers", headers)
|
183
|
+
event.set("host", remote_address)
|
184
|
+
decorate(event)
|
185
|
+
@queue << event
|
186
|
+
end
|
187
|
+
|
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
|
+
def validate_ssl_settings!
|
204
|
+
if !@ssl
|
205
|
+
@logger.warn("SSL Certificate will not be used") if @ssl_certificate
|
206
|
+
@logger.warn("SSL Key will not be used") if @ssl_key
|
207
|
+
@logger.warn("SSL Java Key Store will not be used") if @keystore
|
208
|
+
elsif !(ssl_key_configured? || ssl_jks_configured?)
|
209
|
+
raise LogStash::ConfigurationError, "Certificate or JKS must be configured"
|
210
|
+
end
|
211
|
+
|
212
|
+
if @ssl && original_params.key?("verify_mode")
|
213
|
+
if original_params.key?("ssl_verify_mode")
|
214
|
+
raise LogStash::ConfigurationError, "Both 'ssl_verify_mode' and 'verify_mode' were set. Use only 'ssl_verify_mode'."
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
if @ssl && require_certificate_authorities? && !client_authentication?
|
219
|
+
raise LogStash::ConfigurationError, "Using `ssl_verify_mode` or `verify_mode` set to PEER or FORCE_PEER, requires the configuration of `ssl_certificate_authorities`"
|
220
|
+
elsif @ssl && !require_certificate_authorities? && client_authentication?
|
221
|
+
raise LogStash::ConfigurationError, "The configuration of `ssl_certificate_authorities` requires setting `ssl_verify_mode` or `verify_mode` to PEER or FORCE_PEER"
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
def create_http_server(message_handler)
|
226
|
+
org.logstash.plugins.inputs.http.NettyHttpServer.new(
|
227
|
+
@host, @port, message_handler, build_ssl_params(), @threads, @max_pending_requests, @max_content_length)
|
228
|
+
end
|
229
|
+
|
230
|
+
def build_ssl_params
|
231
|
+
return nil unless @ssl
|
232
|
+
|
233
|
+
if @keystore && @keystore_password
|
234
|
+
ssl_builder = org.logstash.plugins.inputs.http.util.JksSslBuilder.new(@keystore, @keystore_password.value)
|
235
|
+
if original_params.key?("verify_mode")
|
236
|
+
if @verify_mode.upcase == "FORCE_PEER"
|
237
|
+
ssl_builder.setVerifyMode(org.logstash.plugins.inputs.http.util.SslBuilder::SslClientVerifyMode::FORCE_PEER)
|
238
|
+
elsif @verify_mode.upcase == "PEER"
|
239
|
+
ssl_builder.setVerifyMode(org.logstash.plugins.inputs.http.util.SslBuilder::SslClientVerifyMode::VERIFY_PEER)
|
240
|
+
end
|
241
|
+
end
|
242
|
+
return ssl_builder
|
243
|
+
end
|
244
|
+
|
245
|
+
begin
|
246
|
+
ssl_builder = org.logstash.plugins.inputs.http.util.SslSimpleBuilder.new(@ssl_certificate, @ssl_key, @ssl_key_passphrase.nil? ? nil : @ssl_key_passphrase.value)
|
247
|
+
.setProtocols(convert_protocols)
|
248
|
+
.setCipherSuites(normalized_ciphers)
|
249
|
+
rescue java.lang.IllegalArgumentException => e
|
250
|
+
raise LogStash::ConfigurationError.new(e)
|
251
|
+
end
|
252
|
+
|
253
|
+
ssl_builder.setHandshakeTimeoutMilliseconds(@ssl_handshake_timeout)
|
254
|
+
|
255
|
+
if client_authentication?
|
256
|
+
if @ssl_verify_mode.upcase == "FORCE_PEER"
|
257
|
+
ssl_builder.setVerifyMode(org.logstash.plugins.inputs.http.util.SslBuilder::SslClientVerifyMode::FORCE_PEER)
|
258
|
+
elsif @ssl_verify_mode.upcase == "PEER"
|
259
|
+
ssl_builder.setVerifyMode(org.logstash.plugins.inputs.http.util.SslBuilder::SslClientVerifyMode::VERIFY_PEER)
|
260
|
+
end
|
261
|
+
ssl_builder.setCertificateAuthorities(@ssl_certificate_authorities)
|
262
|
+
end
|
263
|
+
ssl_builder
|
264
|
+
end
|
265
|
+
|
266
|
+
def ssl_key_configured?
|
267
|
+
!!(@ssl_certificate && @ssl_key)
|
268
|
+
end
|
269
|
+
|
270
|
+
def ssl_jks_configured?
|
271
|
+
!!(@keystore && @keystore_password)
|
272
|
+
end
|
273
|
+
|
274
|
+
def client_authentication?
|
275
|
+
@ssl_certificate_authorities && @ssl_certificate_authorities.size > 0
|
276
|
+
end
|
277
|
+
|
278
|
+
def require_certificate_authorities?
|
279
|
+
@ssl_verify_mode == "force_peer" || @ssl_verify_mode == "peer"
|
280
|
+
end
|
281
|
+
|
282
|
+
def normalized_ciphers
|
283
|
+
@cipher_suites.map(&:upcase)
|
284
|
+
end
|
285
|
+
|
286
|
+
def convert_protocols
|
287
|
+
TLS.get_supported(@tls_min_version..@tls_max_version).map(&:name)
|
288
|
+
end
|
289
|
+
|
290
|
+
end # class LogStash::Inputs::Http
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "logstash-input-http_jars"
|
3
|
+
java_import org.logstash.plugins.inputs.http.MessageHandler
|
4
|
+
java_import "io.netty.handler.codec.http.DefaultFullHttpResponse"
|
5
|
+
java_import "io.netty.handler.codec.http.HttpHeaderNames"
|
6
|
+
java_import "io.netty.handler.codec.http.HttpVersion"
|
7
|
+
java_import "io.netty.handler.codec.http.HttpResponseStatus"
|
8
|
+
java_import "io.netty.buffer.Unpooled"
|
9
|
+
java_import "io.netty.util.CharsetUtil"
|
10
|
+
|
11
|
+
module LogStash module Inputs class Http
|
12
|
+
class MessageHandler
|
13
|
+
include org.logstash.plugins.inputs.http.IMessageHandler
|
14
|
+
|
15
|
+
attr_reader :input
|
16
|
+
|
17
|
+
def initialize(input, default_codec, additional_codecs)
|
18
|
+
@input = input
|
19
|
+
@default_codec = default_codec
|
20
|
+
@additional_codecs = additional_codecs
|
21
|
+
end
|
22
|
+
|
23
|
+
def onNewMessage(remote_address, message)
|
24
|
+
if valid_auth?(message)
|
25
|
+
message.headers.remove(HttpHeaderNames::AUTHORIZATION)
|
26
|
+
status, headers, content = @input.decode_body(remote_address, message, @default_codec, @additional_codecs)
|
27
|
+
else
|
28
|
+
status, headers, content = 401, {}, 'failed to authenticate'
|
29
|
+
end
|
30
|
+
generate_response(status, headers, content)
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
def generate_response(status, headers, content)
|
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
|
44
|
+
end
|
45
|
+
|
46
|
+
def copy
|
47
|
+
MessageHandler.new(@input, @default_codec.clone, clone_additional_codecs())
|
48
|
+
end
|
49
|
+
|
50
|
+
def clone_additional_codecs
|
51
|
+
clone_additional_codecs = {}
|
52
|
+
@additional_codecs.each do |content_type, codec|
|
53
|
+
clone_additional_codecs[content_type] = codec.clone
|
54
|
+
end
|
55
|
+
clone_additional_codecs
|
56
|
+
end
|
57
|
+
|
58
|
+
def valid_auth?(message)
|
59
|
+
@input.valid_auth?(message.headers.get(HttpHeaderNames::AUTHORIZATION))
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end; end; end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module LogStash module Inputs class Http
|
3
|
+
class TLS
|
4
|
+
class TLSOption
|
5
|
+
include Comparable
|
6
|
+
|
7
|
+
attr_reader :name, :version
|
8
|
+
def initialize(name, version)
|
9
|
+
@name = name
|
10
|
+
@version = version
|
11
|
+
end
|
12
|
+
|
13
|
+
def <=>(other)
|
14
|
+
version <=> other.version
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
TLS_PROTOCOL_OPTIONS = [
|
19
|
+
TLSOption.new("TLSv1", 1),
|
20
|
+
TLSOption.new("TLSv1.1", 1.1),
|
21
|
+
TLSOption.new("TLSv1.2", 1.2)
|
22
|
+
]
|
23
|
+
|
24
|
+
def self.min
|
25
|
+
TLS_PROTOCOL_OPTIONS.min
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.max
|
29
|
+
TLS_PROTOCOL_OPTIONS.max
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.get_supported(versions)
|
33
|
+
if versions.is_a?(Range)
|
34
|
+
TLS_PROTOCOL_OPTIONS.select { |tls| versions.cover?(tls.version) }
|
35
|
+
else
|
36
|
+
TLS_PROTOCOL_OPTIONS.select { |tls| versions == tls.version }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end; end; end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
class CompressedRequests
|
2
|
+
def initialize(app)
|
3
|
+
@app = app
|
4
|
+
end
|
5
|
+
|
6
|
+
def method_handled?(env)
|
7
|
+
!!(env['REQUEST_METHOD'] =~ /(POST|PUT)/)
|
8
|
+
end
|
9
|
+
|
10
|
+
def encoding_handled?(env)
|
11
|
+
['gzip', 'deflate'].include? env['HTTP_CONTENT_ENCODING']
|
12
|
+
end
|
13
|
+
|
14
|
+
def call(env)
|
15
|
+
if method_handled?(env) && encoding_handled?(env)
|
16
|
+
begin
|
17
|
+
extracted = decode(env['rack.input'], env['HTTP_CONTENT_ENCODING'])
|
18
|
+
rescue Zlib::Error
|
19
|
+
return [400, {'Content-Type' => 'text/plain'}, ["Failed to decompress body"]]
|
20
|
+
end
|
21
|
+
|
22
|
+
env.delete('HTTP_CONTENT_ENCODING')
|
23
|
+
env['CONTENT_LENGTH'] = extracted.bytesize
|
24
|
+
env['rack.input'] = StringIO.new(extracted)
|
25
|
+
end
|
26
|
+
|
27
|
+
@app.call(env)
|
28
|
+
end
|
29
|
+
|
30
|
+
def decode(input, content_encoding)
|
31
|
+
case content_encoding
|
32
|
+
when 'gzip' then
|
33
|
+
Zlib::GzipReader.new(input).read
|
34
|
+
when 'deflate' then
|
35
|
+
Zlib::Inflate.inflate(input.read)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "jars/installer"
|
3
|
+
require "fileutils"
|
4
|
+
|
5
|
+
desc "vendor"
|
6
|
+
task :vendor do
|
7
|
+
exit(1) unless system './gradlew vendor'
|
8
|
+
version = File.read("VERSION").strip
|
9
|
+
end
|
10
|
+
|
11
|
+
desc "clean"
|
12
|
+
task :clean do
|
13
|
+
["build", "vendor/jar-dependencies", "Gemfile.lock"].each do |p|
|
14
|
+
FileUtils.rm_rf(p)
|
15
|
+
end
|
16
|
+
end
|