thin 1.0.0 → 1.2.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of thin might be problematic. Click here for more details.
- data/CHANGELOG +26 -0
- data/example/async_app.ru +126 -0
- data/example/async_chat.ru +247 -0
- data/example/async_tailer.ru +100 -0
- data/example/config.ru +1 -1
- data/ext/thin_parser/parser.c +299 -1065
- data/ext/thin_parser/parser.rl +7 -9
- data/ext/thin_parser/thin.c +36 -36
- data/lib/rack/adapter/rails.rb +31 -23
- data/lib/thin.rb +2 -3
- data/lib/thin/command.rb +4 -3
- data/lib/thin/connection.rb +51 -15
- data/lib/thin/controllers/cluster.rb +7 -1
- data/lib/thin/controllers/controller.rb +1 -0
- data/lib/thin/request.rb +16 -2
- data/lib/thin/response.rb +4 -2
- data/lib/thin/runner.rb +1 -1
- data/lib/thin/version.rb +5 -5
- data/lib/thin_parser.bundle +0 -0
- data/spec/command_spec.rb +6 -1
- data/spec/controllers/cluster_spec.rb +33 -0
- data/spec/controllers/controller_spec.rb +11 -3
- data/spec/request/parser_spec.rb +28 -4
- data/spec/response_spec.rb +8 -0
- data/spec/runner_spec.rb +3 -2
- data/spec/server/pipelining_spec.rb +1 -0
- data/spec/server/stopping_spec.rb +13 -3
- data/spec/spec_helper.rb +2 -2
- data/tasks/gem.rake +9 -3
- metadata +9 -8
- data/COMMITTERS +0 -3
- data/lib/rack/handler/thin.rb +0 -18
@@ -102,7 +102,13 @@ module Thin
|
|
102
102
|
|
103
103
|
def with_each_server
|
104
104
|
if only
|
105
|
-
|
105
|
+
if only < 80
|
106
|
+
# interpret +only+ as a sequence number
|
107
|
+
yield(first_port + only)
|
108
|
+
else
|
109
|
+
# interpret +only+ as an absolute port number
|
110
|
+
yield only
|
111
|
+
end
|
106
112
|
elsif socket || swiftiply?
|
107
113
|
size.times { |n| yield n }
|
108
114
|
else
|
data/lib/thin/request.rb
CHANGED
@@ -16,6 +16,8 @@ module Thin
|
|
16
16
|
|
17
17
|
# Freeze some HTTP header names & values
|
18
18
|
SERVER_SOFTWARE = 'SERVER_SOFTWARE'.freeze
|
19
|
+
SERVER_NAME = 'SERVER_NAME'.freeze
|
20
|
+
LOCALHOST = 'localhost'.freeze
|
19
21
|
HTTP_VERSION = 'HTTP_VERSION'.freeze
|
20
22
|
HTTP_1_0 = 'HTTP/1.0'.freeze
|
21
23
|
REMOTE_ADDR = 'REMOTE_ADDR'.freeze
|
@@ -24,7 +26,7 @@ module Thin
|
|
24
26
|
CONNECTION = 'HTTP_CONNECTION'.freeze
|
25
27
|
KEEP_ALIVE_REGEXP = /\bkeep-alive\b/i.freeze
|
26
28
|
CLOSE_REGEXP = /\bclose\b/i.freeze
|
27
|
-
|
29
|
+
|
28
30
|
# Freeze some Rack header names
|
29
31
|
RACK_INPUT = 'rack.input'.freeze
|
30
32
|
RACK_VERSION = 'rack.version'.freeze
|
@@ -32,6 +34,8 @@ module Thin
|
|
32
34
|
RACK_MULTITHREAD = 'rack.multithread'.freeze
|
33
35
|
RACK_MULTIPROCESS = 'rack.multiprocess'.freeze
|
34
36
|
RACK_RUN_ONCE = 'rack.run_once'.freeze
|
37
|
+
ASYNC_CALLBACK = 'async.callback'.freeze
|
38
|
+
ASYNC_CLOSE = 'async.close'.freeze
|
35
39
|
|
36
40
|
# CGI-like request environment variables
|
37
41
|
attr_reader :env
|
@@ -43,12 +47,13 @@ module Thin
|
|
43
47
|
attr_reader :body
|
44
48
|
|
45
49
|
def initialize
|
46
|
-
@parser = HttpParser.new
|
50
|
+
@parser = Thin::HttpParser.new
|
47
51
|
@data = ''
|
48
52
|
@nparsed = 0
|
49
53
|
@body = StringIO.new
|
50
54
|
@env = {
|
51
55
|
SERVER_SOFTWARE => SERVER,
|
56
|
+
SERVER_NAME => LOCALHOST,
|
52
57
|
|
53
58
|
# Rack stuff
|
54
59
|
RACK_INPUT => @body,
|
@@ -125,6 +130,15 @@ module Thin
|
|
125
130
|
def threaded=(value)
|
126
131
|
@env[RACK_MULTITHREAD] = value
|
127
132
|
end
|
133
|
+
|
134
|
+
def async_callback=(callback)
|
135
|
+
@env[ASYNC_CALLBACK] = callback
|
136
|
+
@env[ASYNC_CLOSE] = EventMachine::DefaultDeferrable.new
|
137
|
+
end
|
138
|
+
|
139
|
+
def async_close
|
140
|
+
@async_close ||= @env[ASYNC_CLOSE]
|
141
|
+
end
|
128
142
|
|
129
143
|
# Close any resource used by the request
|
130
144
|
def close
|
data/lib/thin/response.rb
CHANGED
data/lib/thin/runner.rb
CHANGED
@@ -92,7 +92,7 @@ module Thin
|
|
92
92
|
opts.separator "Cluster options:"
|
93
93
|
|
94
94
|
opts.on("-s", "--servers NUM", "Number of servers to start") { |num| @options[:servers] = num.to_i }
|
95
|
-
opts.on("-o", "--only NUM", "Send command to only one server of the cluster") { |only| @options[:only] = only }
|
95
|
+
opts.on("-o", "--only NUM", "Send command to only one server of the cluster") { |only| @options[:only] = only.to_i }
|
96
96
|
opts.on("-C", "--config FILE", "Load options from config file") { |file| @options[:config] = file }
|
97
97
|
opts.on( "--all [DIR]", "Send command to each config files in DIR") { |dir| @options[:all] = dir } if Thin.linux?
|
98
98
|
end
|
data/lib/thin/version.rb
CHANGED
@@ -5,21 +5,21 @@ module Thin
|
|
5
5
|
|
6
6
|
module VERSION #:nodoc:
|
7
7
|
MAJOR = 1
|
8
|
-
MINOR =
|
9
|
-
TINY =
|
8
|
+
MINOR = 2
|
9
|
+
TINY = 1
|
10
10
|
|
11
11
|
STRING = [MAJOR, MINOR, TINY].join('.')
|
12
12
|
|
13
|
-
CODENAME = "
|
13
|
+
CODENAME = "Asynctilicious Ultra Supreme".freeze
|
14
14
|
|
15
|
-
RACK = [
|
15
|
+
RACK = [1, 0].freeze # Rack protocol version
|
16
16
|
end
|
17
17
|
|
18
18
|
NAME = 'thin'.freeze
|
19
19
|
SERVER = "#{NAME} #{VERSION::STRING} codename #{VERSION::CODENAME}".freeze
|
20
20
|
|
21
21
|
def self.win?
|
22
|
-
RUBY_PLATFORM =~ /mswin/
|
22
|
+
RUBY_PLATFORM =~ /mswin|mingw/
|
23
23
|
end
|
24
24
|
|
25
25
|
def self.linux?
|
Binary file
|
data/spec/command_spec.rb
CHANGED
@@ -4,7 +4,7 @@ describe Command do
|
|
4
4
|
before do
|
5
5
|
Command.script = 'thin'
|
6
6
|
@command = Command.new(:start, :port => 3000, :daemonize => true, :log => 'hi.log',
|
7
|
-
:require => %w(rubygems thin))
|
7
|
+
:require => %w(rubygems thin), :no_epoll => true)
|
8
8
|
end
|
9
9
|
|
10
10
|
it 'should shellify command' do
|
@@ -17,4 +17,9 @@ describe Command do
|
|
17
17
|
out = @command.shellify
|
18
18
|
out.should include('--require="rubygems"', '--require="thin"')
|
19
19
|
end
|
20
|
+
|
21
|
+
it 'should convert _ to - in option name' do
|
22
|
+
out = @command.shellify
|
23
|
+
out.should include('--no-epoll')
|
24
|
+
end
|
20
25
|
end
|
@@ -135,6 +135,39 @@ describe Cluster, "controlling only one server" do
|
|
135
135
|
end
|
136
136
|
end
|
137
137
|
|
138
|
+
describe Cluster, "controlling only one server, by sequence number" do
|
139
|
+
before do
|
140
|
+
@cluster = Cluster.new(:chdir => '/rails_app',
|
141
|
+
:address => '0.0.0.0',
|
142
|
+
:port => 3000,
|
143
|
+
:servers => 3,
|
144
|
+
:timeout => 10,
|
145
|
+
:log => 'thin.log',
|
146
|
+
:pid => 'thin.pid',
|
147
|
+
:only => 1
|
148
|
+
)
|
149
|
+
end
|
150
|
+
|
151
|
+
it 'should call only specified server' do
|
152
|
+
calls = []
|
153
|
+
@cluster.send(:with_each_server) do |n|
|
154
|
+
calls << n
|
155
|
+
end
|
156
|
+
calls.should == [3001]
|
157
|
+
end
|
158
|
+
|
159
|
+
it "should start only specified server" do
|
160
|
+
Command.should_receive(:run).with(:start, options_for_port(3001))
|
161
|
+
|
162
|
+
@cluster.start
|
163
|
+
end
|
164
|
+
|
165
|
+
private
|
166
|
+
def options_for_port(port)
|
167
|
+
{ :daemonize => true, :log => "thin.#{port}.log", :timeout => 10, :address => "0.0.0.0", :port => port, :pid => "thin.#{port}.pid", :chdir => "/rails_app" }
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
138
171
|
describe Cluster, "with Swiftiply" do
|
139
172
|
before do
|
140
173
|
@cluster = Cluster.new(:chdir => '/rails_app',
|
@@ -63,14 +63,14 @@ describe Controller, 'start' do
|
|
63
63
|
end
|
64
64
|
|
65
65
|
it "should load app from Rack config" do
|
66
|
-
@controller.options[:rackup] = File.dirname(__FILE__) + '/../../example/config.ru'
|
66
|
+
@controller.options[:rackup] = File.dirname(__FILE__) + '/../../example/config.ru'
|
67
67
|
@controller.start
|
68
68
|
|
69
69
|
@server.app.class.should == Proc
|
70
70
|
end
|
71
71
|
|
72
72
|
it "should load app from ruby file" do
|
73
|
-
@controller.options[:rackup] =
|
73
|
+
@controller.options[:rackup] = File.dirname(__FILE__) + '/../../example/myapp.rb'
|
74
74
|
@controller.start
|
75
75
|
|
76
76
|
@server.app.should == Myapp
|
@@ -78,7 +78,7 @@ describe Controller, 'start' do
|
|
78
78
|
|
79
79
|
it "should throwup if rackup is not a .ru or .rb file" do
|
80
80
|
proc do
|
81
|
-
@controller.options[:rackup] =
|
81
|
+
@controller.options[:rackup] = File.dirname(__FILE__) + '/../../example/myapp.foo'
|
82
82
|
@controller.start
|
83
83
|
end.should raise_error(RuntimeError, /please/)
|
84
84
|
end
|
@@ -89,6 +89,14 @@ describe Controller, 'start' do
|
|
89
89
|
|
90
90
|
@server.threaded.should be_true
|
91
91
|
end
|
92
|
+
|
93
|
+
it "should set RACK_ENV" do
|
94
|
+
@controller.options[:rackup] = File.dirname(__FILE__) + '/../../example/config.ru'
|
95
|
+
@controller.options[:environment] = "lolcat"
|
96
|
+
@controller.start
|
97
|
+
|
98
|
+
ENV['RACK_ENV'].should == "lolcat"
|
99
|
+
end
|
92
100
|
|
93
101
|
end
|
94
102
|
|
data/spec/request/parser_spec.rb
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/../spec_helper'
|
2
2
|
|
3
|
+
# Require mongrel so we can test that Thin parser don't clash w/ Mongrel parser.
|
4
|
+
begin
|
5
|
+
require 'mongrel'
|
6
|
+
rescue LoadError
|
7
|
+
warn "Install mongrel to test compatibility w/ it"
|
8
|
+
end
|
9
|
+
|
3
10
|
describe Request, 'parser' do
|
4
11
|
it 'should include basic headers' do
|
5
12
|
request = R("GET / HTTP/1.1\r\nHost: localhost\r\n\r\n")
|
@@ -52,7 +59,7 @@ describe Request, 'parser' do
|
|
52
59
|
it 'should parse headers from GET request' do
|
53
60
|
request = R(<<-EOS, true)
|
54
61
|
GET / HTTP/1.1
|
55
|
-
Host:
|
62
|
+
Host: myhost.com:3000
|
56
63
|
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en-US; rv:1.8.1.9) Gecko/20071025 Firefox/2.0.0.9
|
57
64
|
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
58
65
|
Accept-Language: en-us,en;q=0.5
|
@@ -63,8 +70,8 @@ Keep-Alive: 300
|
|
63
70
|
Connection: keep-alive
|
64
71
|
|
65
72
|
EOS
|
66
|
-
request.env['HTTP_HOST'].should == '
|
67
|
-
request.env['SERVER_NAME'].should == '
|
73
|
+
request.env['HTTP_HOST'].should == 'myhost.com:3000'
|
74
|
+
request.env['SERVER_NAME'].should == 'myhost.com'
|
68
75
|
request.env['SERVER_PORT'].should == '3000'
|
69
76
|
request.env['HTTP_COOKIE'].should == 'mium=7'
|
70
77
|
|
@@ -167,7 +174,7 @@ EOS
|
|
167
174
|
sorta_safe = %(GET #{path} HTTP/1.1\r\n\r\n)
|
168
175
|
nread = parser.execute(req, sorta_safe, 0)
|
169
176
|
|
170
|
-
sorta_safe.size.should == nread
|
177
|
+
sorta_safe.size.should == nread - 1 # Ragel 6 skips last linebreak
|
171
178
|
parser.should be_finished
|
172
179
|
parser.should_not be_error
|
173
180
|
end
|
@@ -188,4 +195,21 @@ EOS
|
|
188
195
|
it "should fails on heders larger then MAX_HEADER" do
|
189
196
|
proc { R("GET / HTTP/1.1\r\nFoo: #{'X' * Request::MAX_HEADER}\r\n\r\n") }.should raise_error(InvalidRequest)
|
190
197
|
end
|
198
|
+
|
199
|
+
it "should default SERVER_NAME to localhost" do
|
200
|
+
request = R("GET / HTTP/1.1\r\n\r\n")
|
201
|
+
request.env['SERVER_NAME'].should == "localhost"
|
202
|
+
end
|
203
|
+
|
204
|
+
it 'should normalize http_fields' do
|
205
|
+
[ "GET /index.html HTTP/1.1\r\nhos-t: localhost\r\n\r\n",
|
206
|
+
"GET /index.html HTTP/1.1\r\nhOs_t: localhost\r\n\r\n",
|
207
|
+
"GET /index.html HTTP/1.1\r\nhoS-T: localhost\r\n\r\n"
|
208
|
+
].each { |req_str|
|
209
|
+
parser = HttpParser.new
|
210
|
+
req = {}
|
211
|
+
nread = parser.execute(req, req_str, 0)
|
212
|
+
req.should be_has_key('HTTP_HOS_T')
|
213
|
+
}
|
214
|
+
end
|
191
215
|
end
|
data/spec/response_spec.rb
CHANGED
@@ -52,6 +52,14 @@ describe Response do
|
|
52
52
|
end
|
53
53
|
|
54
54
|
it 'should output body' do
|
55
|
+
@response.body = ['<html>', '</html>']
|
56
|
+
|
57
|
+
out = ''
|
58
|
+
@response.each { |l| out << l }
|
59
|
+
out.should include("\r\n\r\n<html></html>")
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'should output String body' do
|
55
63
|
@response.body = '<html></html>'
|
56
64
|
|
57
65
|
out = ''
|
data/spec/runner_spec.rb
CHANGED
@@ -2,10 +2,11 @@ require File.dirname(__FILE__) + '/spec_helper'
|
|
2
2
|
|
3
3
|
describe Runner do
|
4
4
|
it "should parse options" do
|
5
|
-
runner = Runner.new(%w(start --pid test.pid --port 5000))
|
5
|
+
runner = Runner.new(%w(start --pid test.pid --port 5000 -o 3000))
|
6
6
|
|
7
7
|
runner.options[:pid].should == 'test.pid'
|
8
8
|
runner.options[:port].should == 5000
|
9
|
+
runner.options[:only].should == 3000
|
9
10
|
end
|
10
11
|
|
11
12
|
it "should parse specified command" do
|
@@ -164,4 +165,4 @@ describe Runner, "service" do
|
|
164
165
|
|
165
166
|
runner.run!
|
166
167
|
end
|
167
|
-
end
|
168
|
+
end
|
@@ -5,13 +5,21 @@ describe Server, "stopping" do
|
|
5
5
|
start_server do |env|
|
6
6
|
[200, { 'Content-Type' => 'text/html' }, ['ok']]
|
7
7
|
end
|
8
|
+
@done = false
|
8
9
|
end
|
9
10
|
|
10
11
|
it "should wait for current requests before soft stopping" do
|
11
12
|
socket = TCPSocket.new('0.0.0.0', 3333)
|
12
13
|
socket.write("GET / HTTP/1.1")
|
13
|
-
|
14
|
-
|
14
|
+
EventMachine.next_tick do
|
15
|
+
@server.stop # Stop the server in the middle of a request
|
16
|
+
socket.write("\r\n\r\n")
|
17
|
+
@done = true
|
18
|
+
end
|
19
|
+
|
20
|
+
timeout(2) do
|
21
|
+
Thread.pass until @done
|
22
|
+
end
|
15
23
|
|
16
24
|
out = socket.read
|
17
25
|
socket.close
|
@@ -36,7 +44,9 @@ describe Server, "stopping" do
|
|
36
44
|
socket.write("GET / HTTP/1.1")
|
37
45
|
@server.stop! # Force stop the server in the middle of a request
|
38
46
|
|
39
|
-
EventMachine.next_tick
|
47
|
+
EventMachine.next_tick do
|
48
|
+
socket.should be_closed
|
49
|
+
end
|
40
50
|
end
|
41
51
|
|
42
52
|
after do
|
data/spec/spec_helper.rb
CHANGED
@@ -63,7 +63,7 @@ module Matchers
|
|
63
63
|
class ValidateWithLint
|
64
64
|
def matches?(request)
|
65
65
|
@request = request
|
66
|
-
Rack::Lint.new(proc{[200, {'Content-Type' => 'text/html'}, []]}).call(@request.env)
|
66
|
+
Rack::Lint.new(proc{[200, {'Content-Type' => 'text/html', 'Content-Length' => '0'}, []]}).call(@request.env)
|
67
67
|
true
|
68
68
|
rescue Rack::Lint::LintError => e
|
69
69
|
@message = e.message
|
@@ -71,7 +71,7 @@ module Matchers
|
|
71
71
|
end
|
72
72
|
|
73
73
|
def failure_message(negation=nil)
|
74
|
-
"should#{negation} validate with Rack Lint"
|
74
|
+
"should#{negation} validate with Rack Lint: #{@message}"
|
75
75
|
end
|
76
76
|
|
77
77
|
def negative_failure_message
|
data/tasks/gem.rake
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'rake/gempackagetask'
|
2
|
+
require 'yaml'
|
2
3
|
|
3
4
|
WIN_SUFFIX = ENV['WIN_SUFFIX'] || 'i386-mswin32'
|
4
5
|
|
@@ -19,13 +20,13 @@ spec = Gem::Specification.new do |s|
|
|
19
20
|
|
20
21
|
s.required_ruby_version = '>= 1.8.5'
|
21
22
|
|
22
|
-
s.add_dependency 'rack', '>= 0.
|
23
|
-
s.add_dependency 'eventmachine', '>= 0.12.
|
23
|
+
s.add_dependency 'rack', '>= 1.0.0'
|
24
|
+
s.add_dependency 'eventmachine', '>= 0.12.6'
|
24
25
|
unless WIN
|
25
26
|
s.add_dependency 'daemons', '>= 1.0.9'
|
26
27
|
end
|
27
28
|
|
28
|
-
s.files = %w(COPYING CHANGELOG
|
29
|
+
s.files = %w(COPYING CHANGELOG README Rakefile) +
|
29
30
|
Dir.glob("{benchmark,bin,doc,example,lib,spec,tasks}/**/*") +
|
30
31
|
Dir.glob("ext/**/*.{h,c,rb,rl}")
|
31
32
|
|
@@ -58,6 +59,11 @@ end
|
|
58
59
|
task :gem => :tag_warn
|
59
60
|
|
60
61
|
namespace :gem do
|
62
|
+
desc "Update the gemspec for GitHub's gem server"
|
63
|
+
task :github do
|
64
|
+
File.open("thin.gemspec", 'w') { |f| f << YAML.dump(spec) }
|
65
|
+
end
|
66
|
+
|
61
67
|
desc 'Upload gem to code.macournoyer.com'
|
62
68
|
task :upload => :gem do
|
63
69
|
upload "pkg/#{spec.full_name}.gem", 'gems'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: thin
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Marc-Andre Cournoyer
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date:
|
12
|
+
date: 2009-05-01 00:00:00 -04:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -20,7 +20,7 @@ dependencies:
|
|
20
20
|
requirements:
|
21
21
|
- - ">="
|
22
22
|
- !ruby/object:Gem::Version
|
23
|
-
version: 0.
|
23
|
+
version: 1.0.0
|
24
24
|
version:
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: eventmachine
|
@@ -30,7 +30,7 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 0.12.
|
33
|
+
version: 0.12.6
|
34
34
|
version:
|
35
35
|
- !ruby/object:Gem::Dependency
|
36
36
|
name: daemons
|
@@ -53,7 +53,6 @@ extra_rdoc_files: []
|
|
53
53
|
files:
|
54
54
|
- COPYING
|
55
55
|
- CHANGELOG
|
56
|
-
- COMMITTERS
|
57
56
|
- README
|
58
57
|
- Rakefile
|
59
58
|
- benchmark/abc
|
@@ -61,6 +60,9 @@ files:
|
|
61
60
|
- benchmark/runner
|
62
61
|
- bin/thin
|
63
62
|
- example/adapter.rb
|
63
|
+
- example/async_app.ru
|
64
|
+
- example/async_chat.ru
|
65
|
+
- example/async_tailer.ru
|
64
66
|
- example/config.ru
|
65
67
|
- example/monit_sockets
|
66
68
|
- example/monit_unixsock
|
@@ -74,8 +76,6 @@ files:
|
|
74
76
|
- lib/rack/adapter
|
75
77
|
- lib/rack/adapter/loader.rb
|
76
78
|
- lib/rack/adapter/rails.rb
|
77
|
-
- lib/rack/handler
|
78
|
-
- lib/rack/handler/thin.rb
|
79
79
|
- lib/thin
|
80
80
|
- lib/thin/backends
|
81
81
|
- lib/thin/backends/base.rb
|
@@ -101,6 +101,7 @@ files:
|
|
101
101
|
- lib/thin/statuses.rb
|
102
102
|
- lib/thin/version.rb
|
103
103
|
- lib/thin.rb
|
104
|
+
- lib/thin_parser.bundle
|
104
105
|
- spec/backends
|
105
106
|
- spec/backends/swiftiply_client_spec.rb
|
106
107
|
- spec/backends/tcp_server_spec.rb
|
@@ -240,7 +241,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
240
241
|
requirements: []
|
241
242
|
|
242
243
|
rubyforge_project: thin
|
243
|
-
rubygems_version: 1.
|
244
|
+
rubygems_version: 1.3.1
|
244
245
|
signing_key:
|
245
246
|
specification_version: 2
|
246
247
|
summary: A thin and fast web server
|