thick 0.0.4-java → 0.0.5-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.
- data/CHANGELOG.md +7 -1
- data/README.md +2 -0
- data/ROADMAP.md +1 -2
- data/bin/thick +13 -12
- data/lib/jars/netty-3.5.11.Final.jar +0 -0
- data/lib/thick/async_response.rb +37 -2
- data/lib/thick/controller.rb +88 -0
- data/lib/thick/java.rb +12 -0
- data/lib/thick/loader.rb +20 -0
- data/lib/thick/pipeline_factory.rb +3 -44
- data/lib/thick/server.rb +8 -14
- data/lib/thick/server_handler.rb +16 -7
- data/lib/thick/thick.rb +29 -0
- data/lib/thick/version.rb +1 -1
- data/lib/thick.rb +6 -2
- metadata +97 -62
- data/lib/jars/netty-3.4.0.Alpha2.jar +0 -0
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
Thick is very lightweight web server for JRuby based on excellent Netty library.
|
4
4
|
|
5
|
+
[](http://travis-ci.org/marekjelen/thick)
|
6
|
+
|
5
7
|
## Status
|
6
8
|
|
7
9
|
Works on several Sinatra and Rails applications. No real testing, yet.
|
data/ROADMAP.md
CHANGED
data/bin/thick
CHANGED
@@ -2,7 +2,6 @@
|
|
2
2
|
require 'optparse'
|
3
3
|
|
4
4
|
require 'rubygems'
|
5
|
-
require 'rack'
|
6
5
|
|
7
6
|
$: << File.expand_path('../../lib', __FILE__)
|
8
7
|
require 'thick'
|
@@ -27,20 +26,22 @@ OptionParser.new do |opts|
|
|
27
26
|
options[:port] = Integer(port)
|
28
27
|
end
|
29
28
|
|
30
|
-
opts.on('-
|
31
|
-
options[:
|
29
|
+
opts.on('-f', '--file FILE', 'use FILE to load the application (default: config.ru)') do |file|
|
30
|
+
options[:file] = file
|
32
31
|
end
|
33
32
|
|
34
|
-
|
33
|
+
opts.on('-d', '--directory DIR', 'use DIR as default directory (default: cwd)') do |directory|
|
34
|
+
options[:directory] = directory
|
35
|
+
end
|
35
36
|
|
36
|
-
|
37
|
-
options[:
|
38
|
-
|
37
|
+
opts.on('-E', '--env ENVIRONMENT', 'use ENVIRONMENT for defaults (default: development)') do |e|
|
38
|
+
options[:environment] = e
|
39
|
+
end
|
39
40
|
|
40
|
-
|
41
|
+
opts.on('-C', '--controller', 'starts controller for remote monitoring and management') do |e|
|
42
|
+
options[:controller] = e
|
43
|
+
end
|
41
44
|
|
42
|
-
|
43
|
-
app = Rack::Builder.parse_file('config.ru')
|
45
|
+
end.parse!
|
44
46
|
|
45
|
-
|
46
|
-
Thick.start(app[0], options)
|
47
|
+
Thick.start(options)
|
Binary file
|
data/lib/thick/async_response.rb
CHANGED
@@ -8,15 +8,26 @@ module Thick
|
|
8
8
|
@custom = false
|
9
9
|
@async = false
|
10
10
|
@block = nil
|
11
|
+
@chunked = false
|
12
|
+
@content_length = nil
|
13
|
+
@closed = false
|
11
14
|
@params = []
|
12
15
|
end
|
13
16
|
|
14
17
|
def call(chunk)
|
15
|
-
|
18
|
+
chunk = Thick::Java::ChannelBuffers.copiedBuffer(chunk.to_s, Thick::Java::CharsetUtil::UTF_8)
|
19
|
+
chunk = Thick::Java::DefaultHttpChunk.new(chunk) if @chunked
|
20
|
+
@context.channel.write(chunk) unless closed?
|
16
21
|
end
|
17
22
|
|
18
23
|
def close
|
19
|
-
@
|
24
|
+
if @chunked
|
25
|
+
chunk = Thick::Java::ChannelBuffers.copiedBuffer("0\r\n\r\n", Thick::Java::CharsetUtil::UTF_8)
|
26
|
+
else
|
27
|
+
chunk = Thick::Java::ChannelBuffers::EMPTY_BUFFER
|
28
|
+
end
|
29
|
+
@context.channel.write(chunk).addListener(Thick::Java::ChannelFutureListener::CLOSE) unless closed?
|
30
|
+
closed!
|
20
31
|
end
|
21
32
|
|
22
33
|
def ready!
|
@@ -48,6 +59,30 @@ module Thick
|
|
48
59
|
@async
|
49
60
|
end
|
50
61
|
|
62
|
+
def chunked!
|
63
|
+
@chunked = true
|
64
|
+
end
|
65
|
+
|
66
|
+
def chunked?
|
67
|
+
@chunked
|
68
|
+
end
|
69
|
+
|
70
|
+
def content_length!(length)
|
71
|
+
@content_length = length
|
72
|
+
end
|
73
|
+
|
74
|
+
def content_length
|
75
|
+
@content_length
|
76
|
+
end
|
77
|
+
|
78
|
+
def closed!
|
79
|
+
@closed = true
|
80
|
+
end
|
81
|
+
|
82
|
+
def closed?
|
83
|
+
@closed
|
84
|
+
end
|
85
|
+
|
51
86
|
end
|
52
87
|
|
53
88
|
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
module Thick
|
2
|
+
class Controller
|
3
|
+
|
4
|
+
def initialize(options, server)
|
5
|
+
@options = options
|
6
|
+
@server = server
|
7
|
+
@factory = Thick::Java::NioServerSocketChannelFactory.new(Thick::Java::Executors.new_cached_thread_pool, Thick::Java::Executors.new_cached_thread_pool)
|
8
|
+
@bootstrap = Thick::Java::ServerBootstrap.new(@factory)
|
9
|
+
@bootstrap.pipeline_factory = Controller::PipelineFactory.new(@options)
|
10
|
+
end
|
11
|
+
|
12
|
+
def start
|
13
|
+
@channel = @bootstrap.bind(Thick::Java::InetSocketAddress.new('127.0.0.1', 9393))
|
14
|
+
puts "* Controller started on 127.0.0.1:9393"
|
15
|
+
self
|
16
|
+
end
|
17
|
+
|
18
|
+
def stop
|
19
|
+
@channel.close
|
20
|
+
self
|
21
|
+
end
|
22
|
+
|
23
|
+
class PipelineFactory
|
24
|
+
|
25
|
+
include Thick::Java::ChannelPipelineFactory
|
26
|
+
|
27
|
+
def initialize(options)
|
28
|
+
@options = options
|
29
|
+
end
|
30
|
+
|
31
|
+
def getPipeline
|
32
|
+
pipeline = Thick::Java::Channels.pipeline
|
33
|
+
pipeline.add_last('decoder', Thick::Java::HttpRequestDecoder.new)
|
34
|
+
pipeline.add_last('aggregator', Thick::Java::HttpChunkAggregator.new(65536))
|
35
|
+
pipeline.add_last('encoder', Thick::Java::HttpResponseEncoder.new)
|
36
|
+
pipeline.add_last('handler', Controller::Handler.new(@options))
|
37
|
+
pipeline
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
class Handler < Thick::Java::SimpleChannelUpstreamHandler
|
43
|
+
|
44
|
+
def messageReceived(context, event)
|
45
|
+
message = event.message
|
46
|
+
case message
|
47
|
+
when Thick::Java::HttpRequest
|
48
|
+
handle_request(context, message)
|
49
|
+
when Thick::Java::WebSocketFrame
|
50
|
+
handle_websocket_frame(context, message)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def handle_request(context, request)
|
55
|
+
url = "ws://" + request.get_header(Thick::Java::HttpHeaders::Names::HOST) + '/controller'
|
56
|
+
factory = Thick::Java::WebSocketServerHandshakerFactory.new(url, nil, false)
|
57
|
+
@handshaker = factory.new_handshaker(request)
|
58
|
+
if @handshaker
|
59
|
+
@handshaker.handshake(context, request)
|
60
|
+
else
|
61
|
+
factory.send_unsupported_webSocket_version_response(context)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def handle_websocket_frame(context, frame)
|
66
|
+
case frame
|
67
|
+
when Thick::Java::CloseWebSocketFrame
|
68
|
+
@handshaker.close(context, frame)
|
69
|
+
when Thick::Java::PingWebSocketFrame
|
70
|
+
context.channel.write(Thick::Java::PongWebSocketFrame.new(frame.binary_data))
|
71
|
+
when Thick::Java::TextWebSocketFrame
|
72
|
+
handle_websocket_message(context, frame.text)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def websocket_send(context, message)
|
77
|
+
context.channel.write(Thick::Java::TextWebSocketFrame.new(message.to_s))
|
78
|
+
end
|
79
|
+
|
80
|
+
def handle_websocket_message(context, message)
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
data/lib/thick/java.rb
CHANGED
@@ -8,16 +8,24 @@ module Thick
|
|
8
8
|
java_import 'org.jboss.netty.buffer.ChannelBuffer'
|
9
9
|
java_import 'org.jboss.netty.buffer.ChannelBufferInputStream'
|
10
10
|
java_import 'org.jboss.netty.buffer.ChannelBuffers'
|
11
|
+
java_import 'org.jboss.netty.handler.codec.http.DefaultHttpChunk'
|
11
12
|
java_import 'org.jboss.netty.handler.codec.http.DefaultHttpResponse'
|
12
13
|
java_import 'org.jboss.netty.handler.codec.http.HttpContentDecompressor'
|
13
14
|
java_import 'org.jboss.netty.handler.codec.http.HttpHeaders'
|
14
15
|
java_import 'org.jboss.netty.handler.codec.http.HttpChunk'
|
16
|
+
java_import 'org.jboss.netty.handler.codec.http.HttpChunkAggregator'
|
15
17
|
java_import 'org.jboss.netty.handler.codec.http.HttpRequest'
|
16
18
|
java_import 'org.jboss.netty.handler.codec.http.HttpRequestDecoder'
|
17
19
|
java_import 'org.jboss.netty.handler.codec.http.HttpResponseEncoder'
|
18
20
|
java_import 'org.jboss.netty.handler.codec.http.HttpResponseStatus'
|
19
21
|
java_import 'org.jboss.netty.handler.codec.http.HttpVersion'
|
20
22
|
java_import 'org.jboss.netty.handler.codec.http.QueryStringDecoder'
|
23
|
+
java_import 'org.jboss.netty.handler.codec.http.websocketx.CloseWebSocketFrame'
|
24
|
+
java_import 'org.jboss.netty.handler.codec.http.websocketx.PingWebSocketFrame'
|
25
|
+
java_import 'org.jboss.netty.handler.codec.http.websocketx.PongWebSocketFrame'
|
26
|
+
java_import 'org.jboss.netty.handler.codec.http.websocketx.TextWebSocketFrame'
|
27
|
+
java_import 'org.jboss.netty.handler.codec.http.websocketx.WebSocketFrame'
|
28
|
+
java_import 'org.jboss.netty.handler.codec.http.websocketx.WebSocketServerHandshakerFactory'
|
21
29
|
java_import 'org.jboss.netty.handler.codec.spdy.SpdyFrameDecoder'
|
22
30
|
java_import 'org.jboss.netty.handler.codec.spdy.SpdyFrameEncoder'
|
23
31
|
java_import 'org.jboss.netty.handler.codec.spdy.SpdySessionHandler'
|
@@ -36,6 +44,10 @@ module Thick
|
|
36
44
|
java_import 'org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory'
|
37
45
|
java_import 'org.jboss.netty.logging.InternalLogLevel'
|
38
46
|
java_import 'org.jboss.netty.util.CharsetUtil'
|
47
|
+
java_import 'org.jruby.CompatVersion'
|
48
|
+
java_import 'org.jruby.embed.AttributeName'
|
49
|
+
java_import 'org.jruby.embed.LocalContextScope'
|
50
|
+
java_import 'org.jruby.embed.ScriptingContainer'
|
39
51
|
|
40
52
|
end
|
41
53
|
end
|
data/lib/thick/loader.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
module Thick
|
2
|
+
|
3
|
+
class Loader
|
4
|
+
|
5
|
+
def initialize(options)
|
6
|
+
@options = options
|
7
|
+
ENV['RACK_ENV'] ||= ENV['RAILS_ENV'] ||= @options[:environment]
|
8
|
+
@application = Rack::Builder.parse_file(@options[:file])[0]
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(env)
|
12
|
+
@application.call(env)
|
13
|
+
rescue => e
|
14
|
+
puts e.message
|
15
|
+
puts e.backtrace
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
@@ -1,57 +1,16 @@
|
|
1
1
|
module Thick
|
2
2
|
|
3
|
-
class TimeProbe
|
4
|
-
|
5
|
-
include Thick::Java::ChannelUpstreamHandler
|
6
|
-
include Thick::Java::ChannelDownstreamHandler
|
7
|
-
|
8
|
-
def self.setup
|
9
|
-
@total = 0
|
10
|
-
@count = 0
|
11
|
-
end
|
12
|
-
|
13
|
-
def initialize
|
14
|
-
@time = Time.now.to_f
|
15
|
-
end
|
16
|
-
|
17
|
-
TimeProbe.setup
|
18
|
-
|
19
|
-
def self.time(time)
|
20
|
-
@total += time
|
21
|
-
@count += 1
|
22
|
-
if @count % 100 == 0
|
23
|
-
puts "AVG: #{@total / @count}"
|
24
|
-
setup
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
def handleUpstream(context, event)
|
29
|
-
context.send_upstream(event)
|
30
|
-
end
|
31
|
-
|
32
|
-
def handleDownstream(context, event)
|
33
|
-
if event.respond_to?(:getState)
|
34
|
-
stop = Time.now.to_f - @time
|
35
|
-
self.class.time(stop)
|
36
|
-
end
|
37
|
-
context.send_downstream(event)
|
38
|
-
end
|
39
|
-
|
40
|
-
end
|
41
|
-
|
42
3
|
class PipelineFactory
|
43
4
|
|
44
5
|
include Thick::Java::ChannelPipelineFactory
|
45
6
|
|
46
|
-
def initialize(
|
47
|
-
@
|
7
|
+
def initialize(options)
|
8
|
+
@options = options
|
48
9
|
@executor = Thick::Java::ExecutionHandler.new(Thick::Java::OrderedMemoryAwareThreadPoolExecutor.new(20, 0, 0))
|
49
10
|
end
|
50
11
|
|
51
12
|
def getPipeline
|
52
13
|
pipeline = Thick::Java::Channels.pipeline
|
53
|
-
|
54
|
-
pipeline.add_last('time_probe', TimeProbe.new)
|
55
14
|
|
56
15
|
pipeline.add_last('http_decoder', Thick::Java::HttpRequestDecoder.new)
|
57
16
|
pipeline.add_last('http_encoder', Thick::Java::HttpResponseEncoder.new)
|
@@ -60,7 +19,7 @@ module Thick
|
|
60
19
|
|
61
20
|
pipeline.add_last('executor', @executor)
|
62
21
|
|
63
|
-
pipeline.add_last('handler', ServerHandler.new(@
|
22
|
+
pipeline.add_last('handler', ServerHandler.new(@options))
|
64
23
|
|
65
24
|
pipeline
|
66
25
|
end
|
data/lib/thick/server.rb
CHANGED
@@ -1,29 +1,23 @@
|
|
1
1
|
module Thick
|
2
2
|
|
3
|
-
def self.start(application, options)
|
4
|
-
@server = Server.new(application)
|
5
|
-
@server.start(:address => options[:address], :port => options[:port])
|
6
|
-
end
|
7
|
-
|
8
3
|
class Server
|
9
4
|
|
10
|
-
def initialize(
|
5
|
+
def initialize(options)
|
6
|
+
@options = options
|
11
7
|
@factory = Thick::Java::NioServerSocketChannelFactory.new(Thick::Java::Executors.new_cached_thread_pool, Thick::Java::Executors.new_cached_thread_pool)
|
12
8
|
@bootstrap = Thick::Java::ServerBootstrap.new(@factory)
|
13
|
-
@bootstrap.pipeline_factory = PipelineFactory.new(
|
9
|
+
@bootstrap.pipeline_factory = PipelineFactory.new(@options)
|
14
10
|
end
|
15
11
|
|
16
|
-
def start
|
17
|
-
@channel = @bootstrap.bind(Thick::Java::InetSocketAddress.new(options[:address], options[:port]))
|
18
|
-
puts
|
19
|
-
|
20
|
-
# ToDo: Is this hack needed?
|
21
|
-
sleep(100)
|
22
|
-
end
|
12
|
+
def start
|
13
|
+
@channel = @bootstrap.bind(Thick::Java::InetSocketAddress.new(@options[:address], @options[:port]))
|
14
|
+
puts "* Server started on #{@options[:address]}:#{@options[:port]}"
|
15
|
+
self
|
23
16
|
end
|
24
17
|
|
25
18
|
def stop
|
26
19
|
@channel.close
|
20
|
+
self
|
27
21
|
end
|
28
22
|
|
29
23
|
end
|
data/lib/thick/server_handler.rb
CHANGED
@@ -1,12 +1,10 @@
|
|
1
|
-
require 'stringio'
|
2
|
-
|
3
1
|
module Thick
|
4
2
|
|
5
3
|
class ServerHandler < Thick::Java::SimpleChannelUpstreamHandler
|
6
4
|
|
7
|
-
def initialize(
|
5
|
+
def initialize(options)
|
8
6
|
super()
|
9
|
-
@
|
7
|
+
@options = options
|
10
8
|
end
|
11
9
|
|
12
10
|
def channelConnected(context, event)
|
@@ -32,7 +30,7 @@ module Thick
|
|
32
30
|
def on_request(context, request)
|
33
31
|
|
34
32
|
# Serve file if exists in public directory
|
35
|
-
file = File.join('public', request.uri)
|
33
|
+
file = File.join(@options[:directory], 'public', request.uri)
|
36
34
|
return serve_file(context, file).addListener(Thick::Java::ChannelFutureListener::CLOSE) if !request.uri.index('..') && File.exists?(file) && !File.directory?(file)
|
37
35
|
|
38
36
|
query_string = request.uri.split('?', 2)
|
@@ -53,7 +51,8 @@ module Thick
|
|
53
51
|
'SERVER_NAME' => 'localhost', # ToDo: Be more precise!
|
54
52
|
'SERVER_PORT' => '8080', # ToDo: Be more precise!
|
55
53
|
# Thick specific
|
56
|
-
'thick.async' => AsyncResponse.new(context)
|
54
|
+
'thick.async' => AsyncResponse.new(context),
|
55
|
+
'thick.options' => @options
|
57
56
|
}
|
58
57
|
|
59
58
|
# Get content length if available
|
@@ -83,7 +82,7 @@ module Thick
|
|
83
82
|
end
|
84
83
|
|
85
84
|
def handle_request(context)
|
86
|
-
response = @application.call(@env)
|
85
|
+
response = @options[:application].call(@env)
|
87
86
|
|
88
87
|
# Let the application make the response as it wants
|
89
88
|
if @env['thick.async'].custom?
|
@@ -102,6 +101,15 @@ module Thick
|
|
102
101
|
Thick::Java::HttpHeaders.set_header(@response, name, value)
|
103
102
|
end
|
104
103
|
|
104
|
+
if @env['thick.async'].async?
|
105
|
+
if length = @env['thick.async'].content_length
|
106
|
+
Thick::Java::HttpHeaders.set_content_length(@response, length)
|
107
|
+
else
|
108
|
+
@response.remove_header('Content-Length')
|
109
|
+
end
|
110
|
+
@response.chunked = true if @env['thick.async'].chunked?
|
111
|
+
end
|
112
|
+
|
105
113
|
context.channel.write(@response)
|
106
114
|
|
107
115
|
# Set content as requested by application
|
@@ -126,6 +134,7 @@ module Thick
|
|
126
134
|
end
|
127
135
|
|
128
136
|
def channelClosed(context, event)
|
137
|
+
@env['thick.async'].closed!
|
129
138
|
end
|
130
139
|
|
131
140
|
def exceptionCaught(context, e)
|
data/lib/thick/thick.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
module Thick
|
2
|
+
|
3
|
+
def self.start(options)
|
4
|
+
@options = {
|
5
|
+
:address => '0.0.0.0',
|
6
|
+
:port => 9292,
|
7
|
+
:environment => 'development',
|
8
|
+
:reloader => false,
|
9
|
+
:controller => false,
|
10
|
+
:directory => Dir.getwd,
|
11
|
+
:file => 'config.ru'
|
12
|
+
}.merge(options)
|
13
|
+
|
14
|
+
puts "* Starting Thick: #{@options.inspect}"
|
15
|
+
|
16
|
+
@options[:application] = Loader.new(@options)
|
17
|
+
@server = Server.new(@options).start
|
18
|
+
|
19
|
+
if @options[:controller]
|
20
|
+
@controller = Controller.new(@options, @server)
|
21
|
+
@controller.start
|
22
|
+
end
|
23
|
+
|
24
|
+
loop do
|
25
|
+
sleep(100) # ToDo: Is this hack needed?
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
data/lib/thick/version.rb
CHANGED
data/lib/thick.rb
CHANGED
@@ -2,12 +2,16 @@ require 'rack'
|
|
2
2
|
|
3
3
|
require 'java'
|
4
4
|
|
5
|
-
require File.expand_path('../jars/netty-3.
|
5
|
+
require File.expand_path('../jars/netty-3.5.11.Final.jar', __FILE__)
|
6
6
|
|
7
7
|
require 'thick/java'
|
8
|
+
require 'thick/thick'
|
8
9
|
require 'thick/version'
|
9
10
|
require 'thick/buffer'
|
10
11
|
require 'thick/async_response'
|
12
|
+
require 'thick/loader'
|
11
13
|
require 'thick/server_handler'
|
12
14
|
require 'thick/pipeline_factory'
|
13
|
-
require 'thick/
|
15
|
+
require 'thick/controller'
|
16
|
+
require 'thick/server'
|
17
|
+
|
metadata
CHANGED
@@ -1,78 +1,113 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: thick
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.5
|
5
|
+
prerelease:
|
6
6
|
platform: java
|
7
|
-
authors:
|
8
|
-
|
9
|
-
autorequire:
|
7
|
+
authors:
|
8
|
+
- Marek Jelen
|
9
|
+
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
12
|
+
date: 2012-11-30 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rack
|
16
|
+
version_requirements: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - '='
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: 1.4.1
|
21
|
+
none: false
|
22
|
+
requirement: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 1.4.1
|
27
|
+
none: false
|
28
|
+
prerelease: false
|
29
|
+
type: :runtime
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rspec
|
32
|
+
version_requirements: !ruby/object:Gem::Requirement
|
33
|
+
requirements:
|
34
|
+
- - '='
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: 2.9.0
|
37
|
+
none: false
|
38
|
+
requirement: !ruby/object:Gem::Requirement
|
39
|
+
requirements:
|
40
|
+
- - '='
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: 2.9.0
|
43
|
+
none: false
|
44
|
+
prerelease: false
|
45
|
+
type: :development
|
26
46
|
description: Very lightweight web server for JRuby based on Netty library.
|
27
|
-
email:
|
28
|
-
|
29
|
-
executables:
|
30
|
-
|
47
|
+
email:
|
48
|
+
- marek@jelen.biz
|
49
|
+
executables:
|
50
|
+
- thick
|
31
51
|
extensions: []
|
32
|
-
|
33
52
|
extra_rdoc_files: []
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
53
|
+
files:
|
54
|
+
- !binary |-
|
55
|
+
YmluL3RoaWNr
|
56
|
+
- !binary |-
|
57
|
+
bGliL3RoaWNrLnJi
|
58
|
+
- !binary |-
|
59
|
+
bGliL3RoaWNrL3BpcGVsaW5lX2ZhY3RvcnkucmI=
|
60
|
+
- !binary |-
|
61
|
+
bGliL3RoaWNrL2phdmEucmI=
|
62
|
+
- !binary |-
|
63
|
+
bGliL3RoaWNrL3RoaWNrLnJi
|
64
|
+
- !binary |-
|
65
|
+
bGliL3RoaWNrL2xvYWRlci5yYg==
|
66
|
+
- !binary |-
|
67
|
+
bGliL3RoaWNrL3ZlcnNpb24ucmI=
|
68
|
+
- !binary |-
|
69
|
+
bGliL3RoaWNrL3NlcnZlcl9oYW5kbGVyLnJi
|
70
|
+
- !binary |-
|
71
|
+
bGliL3RoaWNrL2FzeW5jX3Jlc3BvbnNlLnJi
|
72
|
+
- !binary |-
|
73
|
+
bGliL3RoaWNrL2J1ZmZlci5yYg==
|
74
|
+
- !binary |-
|
75
|
+
bGliL3RoaWNrL2NvbnRyb2xsZXIucmI=
|
76
|
+
- !binary |-
|
77
|
+
bGliL3RoaWNrL3NlcnZlci5yYg==
|
78
|
+
- !binary |-
|
79
|
+
bGliL2phcnMvbmV0dHktMy41LjExLkZpbmFsLmphcg==
|
80
|
+
- LICENSE
|
81
|
+
- README.md
|
82
|
+
- ROADMAP.md
|
83
|
+
- CHANGELOG.md
|
50
84
|
homepage: http://github.com/marekjelen/thick
|
51
85
|
licenses: []
|
52
|
-
|
53
|
-
post_install_message:
|
86
|
+
post_install_message:
|
54
87
|
rdoc_options: []
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
88
|
+
require_paths:
|
89
|
+
- lib
|
90
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - ! '>='
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
segments:
|
95
|
+
- 0
|
96
|
+
version: !binary |-
|
97
|
+
MA==
|
98
|
+
hash: 2
|
59
99
|
none: false
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
100
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - ! '>='
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: !binary |-
|
105
|
+
MA==
|
65
106
|
none: false
|
66
|
-
requirements:
|
67
|
-
- - ">="
|
68
|
-
- !ruby/object:Gem::Version
|
69
|
-
version: "0"
|
70
107
|
requirements: []
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
signing_key:
|
108
|
+
rubyforge_project:
|
109
|
+
rubygems_version: 1.8.24
|
110
|
+
signing_key:
|
75
111
|
specification_version: 3
|
76
112
|
summary: Very lightweight web server for JRuby
|
77
113
|
test_files: []
|
78
|
-
|
Binary file
|