thin 0.6.2-x86-mswin32-60 → 0.6.3-x86-mswin32-60
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 +34 -1
- data/bin/thin +2 -164
- data/example/config.ru +4 -1
- data/example/ramaze.ru +12 -0
- data/example/thin.god +70 -66
- data/lib/rack/adapter/rails.rb +0 -3
- data/lib/rack/handler/thin.rb +6 -1
- data/lib/thin.rb +13 -4
- data/lib/thin/command.rb +9 -5
- data/lib/thin/connection.rb +5 -14
- data/lib/thin/connectors/connector.rb +61 -0
- data/lib/thin/connectors/tcp_server.rb +29 -0
- data/lib/thin/connectors/unix_server.rb +48 -0
- data/lib/thin/controllers/cluster.rb +115 -0
- data/lib/thin/controllers/controller.rb +85 -0
- data/lib/thin/controllers/service.rb +73 -0
- data/lib/thin/controllers/service.sh.erb +39 -0
- data/lib/thin/daemonizing.rb +9 -4
- data/lib/thin/headers.rb +2 -2
- data/lib/thin/runner.rb +166 -0
- data/lib/thin/server.rb +109 -89
- data/lib/thin/stats.html.erb +216 -0
- data/lib/thin/stats.rb +1 -249
- data/lib/thin/version.rb +10 -3
- data/lib/thin_parser.so +0 -0
- data/spec/command_spec.rb +0 -1
- data/spec/configs/cluster.yml +9 -0
- data/spec/configs/single.yml +9 -0
- data/spec/{cluster_spec.rb → controllers/cluster_spec.rb} +22 -10
- data/spec/controllers/controller_spec.rb +85 -0
- data/spec/controllers/service_spec.rb +51 -0
- data/spec/daemonizing_spec.rb +73 -9
- data/spec/request/mongrel_spec.rb +39 -0
- data/spec/{request_spec.rb → request/parser_spec.rb} +11 -143
- data/spec/request/perf_spec.rb +50 -0
- data/spec/request/processing_spec.rb +46 -0
- data/spec/runner_spec.rb +135 -0
- data/spec/server/builder_spec.rb +38 -0
- data/spec/server/stopping_spec.rb +45 -0
- data/spec/server/tcp_spec.rb +54 -0
- data/spec/server/unix_socket_spec.rb +30 -0
- data/spec/spec_helper.rb +49 -16
- data/tasks/announce.rake +7 -3
- data/tasks/email.erb +8 -18
- data/tasks/stats.rake +21 -8
- metadata +33 -7
- data/lib/thin/cluster.rb +0 -123
- data/spec/server_spec.rb +0 -200
@@ -0,0 +1,38 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe Server, 'app builder' do
|
4
|
+
it "should build app from constructor" do
|
5
|
+
server = Server.new('0.0.0.0', 3000, :works)
|
6
|
+
|
7
|
+
server.app.should == :works
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should build app from builder block" do
|
11
|
+
server = Server.new '0.0.0.0', 3000 do
|
12
|
+
run(proc { |env| :works })
|
13
|
+
end
|
14
|
+
|
15
|
+
server.app.call({}).should == :works
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should use middlewares in builder block" do
|
19
|
+
server = Server.new '0.0.0.0', 3000 do
|
20
|
+
use Rack::ShowExceptions
|
21
|
+
run(proc { |env| :works })
|
22
|
+
end
|
23
|
+
|
24
|
+
server.app.class.should == Rack::ShowExceptions
|
25
|
+
server.app.call({}).should == :works
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should work with Rack url mapper" do
|
29
|
+
server = Server.new '0.0.0.0', 3000 do
|
30
|
+
map '/test' do
|
31
|
+
run(proc { |env| :works })
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
server.app.call({})[0].should == 404
|
36
|
+
server.app.call({'PATH_INFO' => '/test'}).should == :works
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe Server, "stopping" do
|
4
|
+
before do
|
5
|
+
start_server do |env|
|
6
|
+
[200, { 'Content-Type' => 'text/html', 'Content-Length' => '2' }, ['ok']]
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should wait for current requests before soft stopping" do
|
11
|
+
socket = TCPSocket.new('0.0.0.0', 3333)
|
12
|
+
socket.write("GET / HTTP/1.1")
|
13
|
+
@server.stop # Stop the server in the middle of a request
|
14
|
+
socket.write("\r\n\r\n")
|
15
|
+
|
16
|
+
out = socket.read
|
17
|
+
socket.close
|
18
|
+
|
19
|
+
out.should_not be_empty
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should not accept new requests when soft stopping" do
|
23
|
+
socket = TCPSocket.new('0.0.0.0', 3333)
|
24
|
+
socket.write("GET / HTTP/1.1")
|
25
|
+
@server.stop # Stop the server in the middle of a request
|
26
|
+
|
27
|
+
EventMachine.next_tick do
|
28
|
+
proc { get('/') }.should raise_error(Errno::ECONNRESET)
|
29
|
+
end
|
30
|
+
|
31
|
+
socket.close
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should drop current requests when hard stopping" do
|
35
|
+
socket = TCPSocket.new('0.0.0.0', 3333)
|
36
|
+
socket.write("GET / HTTP/1.1")
|
37
|
+
@server.stop! # Force stop the server in the middle of a request
|
38
|
+
|
39
|
+
EventMachine.next_tick { socket.should be_closed }
|
40
|
+
end
|
41
|
+
|
42
|
+
after do
|
43
|
+
stop_server
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe Server, 'on TCP socket' do
|
4
|
+
before do
|
5
|
+
start_server do |env|
|
6
|
+
body = env.inspect + env['rack.input'].read
|
7
|
+
[200, { 'Content-Type' => 'text/html', 'Content-Length' => body.size.to_s }, body]
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'should GET from Net::HTTP' do
|
12
|
+
get('/?cthis').should include('cthis')
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'should GET from TCPSocket' do
|
16
|
+
send_data("GET /?this HTTP/1.1\r\n\r\n").
|
17
|
+
should include("HTTP/1.1 200 OK",
|
18
|
+
"Content-Type: text/html", "Content-Length: ",
|
19
|
+
"Connection: close", "this")
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'should return empty string on incomplete headers' do
|
23
|
+
send_data("GET /?this HTTP/1.1\r\nHost:").should be_empty
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'should return empty string on incorrect Content-Length' do
|
27
|
+
send_data("POST / HTTP/1.1\r\nContent-Length: 300\r\n\r\naye").should be_empty
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'should POST from Net::HTTP' do
|
31
|
+
post('/', :arg => 'pirate').should include('arg=pirate')
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'should handle big POST' do
|
35
|
+
big = 'X' * (20 * 1024)
|
36
|
+
post('/', :big => big).should include(big)
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should handle GET in less then #{get_request_time = 0.004} RubySecond" do
|
40
|
+
proc { get('/') }.should be_faster_then(get_request_time)
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should handle POST in less then #{post_request_time = 0.007} RubySecond" do
|
44
|
+
proc { post('/', :file => 'X' * 1000) }.should be_faster_then(post_request_time)
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should retreive remote address" do
|
48
|
+
get('/').should include('"REMOTE_ADDR"=>"127.0.0.1"')
|
49
|
+
end
|
50
|
+
|
51
|
+
after do
|
52
|
+
stop_server
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe Server, "on UNIX domain socket" do
|
4
|
+
before do
|
5
|
+
start_server('/tmp/thin_test.sock') do |env|
|
6
|
+
[200, { 'Content-Type' => 'text/html', 'Content-Length' => env.inspect.size.to_s }, [env.inspect]]
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should accept GET request" do
|
11
|
+
get("/?this").should include('this')
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should retreive remote address" do
|
15
|
+
get('/').should include('"REMOTE_ADDR"=>""') # Is that right?
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should handle GET in less then #{get_request_time = 0.002} RubySecond" do
|
19
|
+
proc { get('/') }.should be_faster_then(get_request_time)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should remove socket file after server stops" do
|
23
|
+
@server.stop!
|
24
|
+
File.exist?('/tmp/thin_test.sock').should be_false
|
25
|
+
end
|
26
|
+
|
27
|
+
after do
|
28
|
+
stop_server
|
29
|
+
end
|
30
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -5,26 +5,13 @@ require 'benchmark'
|
|
5
5
|
require 'timeout'
|
6
6
|
require 'fileutils'
|
7
7
|
require 'benchmark_unit'
|
8
|
+
require 'net/http'
|
9
|
+
require 'socket'
|
8
10
|
|
9
11
|
include Thin
|
10
12
|
|
11
13
|
FileUtils.mkdir_p File.dirname(__FILE__) + '/../log'
|
12
|
-
|
13
|
-
class TestRequest < Thin::Request
|
14
|
-
def initialize(path, verb='GET', params={})
|
15
|
-
@path = path
|
16
|
-
@verb = verb.to_s.upcase
|
17
|
-
@params = {
|
18
|
-
'HTTP_HOST' => 'localhost:3000',
|
19
|
-
'REQUEST_URI' => @path,
|
20
|
-
'REQUEST_PATH' => @path,
|
21
|
-
'REQUEST_METHOD' => @verb,
|
22
|
-
'SCRIPT_NAME' => @path
|
23
|
-
}.merge(params)
|
24
|
-
|
25
|
-
@body = "#{@verb} #{path} HTTP/1.1"
|
26
|
-
end
|
27
|
-
end
|
14
|
+
Command.script = File.dirname(__FILE__) + '/../bin/thin'
|
28
15
|
|
29
16
|
module Matchers
|
30
17
|
class BeFasterThen
|
@@ -139,6 +126,52 @@ module Helpers
|
|
139
126
|
ensure
|
140
127
|
stream.reopen(old_stream)
|
141
128
|
end
|
129
|
+
|
130
|
+
# Create and parse a request
|
131
|
+
def R(raw, convert_line_feed=false)
|
132
|
+
raw.gsub!("\n", "\r\n") if convert_line_feed
|
133
|
+
request = Thin::Request.new
|
134
|
+
request.parse(raw)
|
135
|
+
request
|
136
|
+
end
|
137
|
+
|
138
|
+
def start_server(*args, &app)
|
139
|
+
@server = Thin::Server.new(args[0] || '0.0.0.0', args[1] || 3333, app)
|
140
|
+
@server.timeout = 3
|
141
|
+
@server.silent = true
|
142
|
+
|
143
|
+
@thread = Thread.new { @server.start }
|
144
|
+
sleep 0.1 until @thread.status == 'sleep'
|
145
|
+
end
|
146
|
+
|
147
|
+
def stop_server
|
148
|
+
@server.stop!
|
149
|
+
@thread.kill
|
150
|
+
end
|
151
|
+
|
152
|
+
def send_data(data)
|
153
|
+
if @server.connector.class == Connectors::UnixServer
|
154
|
+
socket = UNIXSocket.new(@server.socket)
|
155
|
+
else
|
156
|
+
socket = TCPSocket.new(@server.host, @server.port)
|
157
|
+
end
|
158
|
+
socket.write data
|
159
|
+
out = socket.read
|
160
|
+
socket.close
|
161
|
+
out
|
162
|
+
end
|
163
|
+
|
164
|
+
def get(url)
|
165
|
+
if @server.connector.class == Connectors::UnixServer
|
166
|
+
send_data("GET #{url} HTTP/1.1\r\n\r\n")
|
167
|
+
else
|
168
|
+
Net::HTTP.get(URI.parse("http://#{@server.host}:#{@server.port}" + url))
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
def post(url, params={})
|
173
|
+
Net::HTTP.post_form(URI.parse("http://#{@server.host}:#{@server.port}" + url), params).body
|
174
|
+
end
|
142
175
|
end
|
143
176
|
|
144
177
|
Spec::Runner.configure do |config|
|
data/tasks/announce.rake
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'erb'
|
2
2
|
|
3
3
|
MSG_TEMPLATE = File.dirname(__FILE__) + '/email.erb'
|
4
|
-
SEND_TO = %w(thin-ruby@googlegroups.com eventmachine-talk@rubyforge.org Rubymtl@lists.artengine.ca ruby-talk@ruby-lang.org)
|
4
|
+
SEND_TO = %w(thin-ruby@googlegroups.com eventmachine-talk@rubyforge.org Rubymtl@lists.artengine.ca ruby-talk@ruby-lang.org montreal-on-rails@googlegroups.com)
|
5
5
|
|
6
6
|
desc 'Generate a template for the new version annoucement'
|
7
7
|
task :ann do
|
@@ -9,10 +9,14 @@ task :ann do
|
|
9
9
|
|
10
10
|
body = <<END_OF_MESSAGE
|
11
11
|
To: #{SEND_TO.join(', ')}
|
12
|
-
Subject: [ANN] Thin #{Thin::VERSION::STRING} #{Thin::VERSION::CODENAME}
|
12
|
+
Subject: [ANN] Thin #{Thin::VERSION::STRING} #{Thin::VERSION::CODENAME} release
|
13
13
|
|
14
14
|
#{msg}
|
15
15
|
END_OF_MESSAGE
|
16
16
|
|
17
|
-
|
17
|
+
`echo "#{body}" | mate`
|
18
|
+
end
|
19
|
+
|
20
|
+
def changelog
|
21
|
+
File.read('CHANGELOG').split("==")[1].split("\n")[1..-1].join("\n")
|
18
22
|
end
|
data/tasks/email.erb
CHANGED
@@ -6,37 +6,27 @@ http://code.macournoyer.com/thin/
|
|
6
6
|
|
7
7
|
== What's new?
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
* Don't read the full body, use direct streaming when sending response.
|
12
|
-
See: Response#each
|
13
|
-
As a result, the Content-Length can not be calculated anymore.
|
14
|
-
You have to do set this in your adapter. All frameworks do it anyway.
|
15
|
-
It improve memory usage and boost speed for low concurrency.
|
16
|
-
Thanks to Kent Sibilev and Ezra for their help on that one.
|
17
|
-
* Add 'Server' response header
|
18
|
-
* Fix --user and --group option not changing daemon process privileges
|
9
|
+
<%= changelog %>
|
19
10
|
|
20
11
|
== Get it!
|
21
12
|
|
22
13
|
sudo gem install thin
|
23
14
|
|
24
|
-
|
25
|
-
--source http://code.macournoyer.com to the command if it doesn't work
|
15
|
+
Or using my mirror:
|
26
16
|
|
27
|
-
|
28
|
-
uninstall it before: sudo gem uninstall thin
|
17
|
+
sudo gem install thin --source http://code.macournoyer.com
|
29
18
|
|
30
19
|
WARNING:
|
31
|
-
Thin is still alpha software, if you use it on your server you understand the
|
32
|
-
risks that are involved.
|
20
|
+
Thin is still alpha software, if you use it on your server you understand the
|
21
|
+
risks that are involved.
|
33
22
|
|
34
23
|
== Contribute
|
35
24
|
|
36
25
|
If you're using Thin, let me know and I'll put your site on http://code.macournoyer.com/thin/users/
|
37
26
|
|
38
|
-
Thin is driven by an active community of passionate coders and benchmarkers.
|
39
|
-
or share some ideas in Thin Google Group:
|
27
|
+
Thin is driven by an active community of passionate coders and benchmarkers.
|
28
|
+
Please join us, contribute or share some ideas in Thin Google Group:
|
29
|
+
http://groups.google.com/group/thin-ruby/topics
|
40
30
|
|
41
31
|
Also on IRC: #thin on freenode
|
42
32
|
|
data/tasks/stats.rake
CHANGED
@@ -3,13 +3,26 @@ task :stats do
|
|
3
3
|
line_count = proc do |path|
|
4
4
|
Dir[path].collect { |f| File.open(f).readlines.reject { |l| l =~ /(^\s*(\#|\/\*))|^\s*$/ }.size }.inject(0){ |sum,n| sum += n }
|
5
5
|
end
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
comment_count = proc do |path|
|
7
|
+
Dir[path].collect { |f| File.open(f).readlines.select { |l| l =~ /^\s*\#/ }.size }.inject(0) { |sum,n| sum += n }
|
8
|
+
end
|
9
|
+
lib = line_count['lib/**/*.rb']
|
10
|
+
comment = comment_count['lib/**/*.rb']
|
11
|
+
ext = line_count['ext/**/*.{c,h}']
|
12
|
+
spec = line_count['spec/**/*.rb']
|
13
|
+
|
14
|
+
comment_ratio = '%1.2f' % (comment.to_f / lib.to_f)
|
15
|
+
spec_ratio = '%1.2f' % (spec.to_f / lib.to_f)
|
10
16
|
|
11
|
-
puts
|
12
|
-
puts
|
13
|
-
puts
|
14
|
-
puts "#{
|
17
|
+
puts '/======================\\'
|
18
|
+
puts '| Part LOC |'
|
19
|
+
puts '|======================|'
|
20
|
+
puts "| lib #{lib.to_s.ljust(5)}|"
|
21
|
+
puts "| lib comments #{comment.to_s.ljust(5)}|"
|
22
|
+
puts "| ext #{ext.to_s.ljust(5)}|"
|
23
|
+
puts "| spec #{spec.to_s.ljust(5)}|"
|
24
|
+
puts '| ratios: |'
|
25
|
+
puts "| lib/comment #{comment_ratio.to_s.ljust(5)}|"
|
26
|
+
puts "| lib/spec #{spec_ratio.to_s.ljust(5)}|"
|
27
|
+
puts '\======================/'
|
15
28
|
end
|
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: 0.6.
|
4
|
+
version: 0.6.3
|
5
5
|
platform: x86-mswin32-60
|
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: 2008-
|
12
|
+
date: 2008-02-07 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -52,6 +52,7 @@ files:
|
|
52
52
|
- example/config.ru
|
53
53
|
- example/monit_sockets
|
54
54
|
- example/monit_unixsock
|
55
|
+
- example/ramaze.ru
|
55
56
|
- example/thin.god
|
56
57
|
- lib/rack
|
57
58
|
- lib/rack/adapter
|
@@ -59,21 +60,38 @@ files:
|
|
59
60
|
- lib/rack/handler
|
60
61
|
- lib/rack/handler/thin.rb
|
61
62
|
- lib/thin
|
62
|
-
- lib/thin/cluster.rb
|
63
63
|
- lib/thin/command.rb
|
64
64
|
- lib/thin/connection.rb
|
65
|
+
- lib/thin/connectors
|
66
|
+
- lib/thin/connectors/connector.rb
|
67
|
+
- lib/thin/connectors/tcp_server.rb
|
68
|
+
- lib/thin/connectors/unix_server.rb
|
69
|
+
- lib/thin/controllers
|
70
|
+
- lib/thin/controllers/cluster.rb
|
71
|
+
- lib/thin/controllers/controller.rb
|
72
|
+
- lib/thin/controllers/service.rb
|
73
|
+
- lib/thin/controllers/service.sh.erb
|
65
74
|
- lib/thin/daemonizing.rb
|
66
75
|
- lib/thin/headers.rb
|
67
76
|
- lib/thin/logging.rb
|
68
77
|
- lib/thin/request.rb
|
69
78
|
- lib/thin/response.rb
|
79
|
+
- lib/thin/runner.rb
|
70
80
|
- lib/thin/server.rb
|
81
|
+
- lib/thin/stats.html.erb
|
71
82
|
- lib/thin/stats.rb
|
72
83
|
- lib/thin/statuses.rb
|
73
84
|
- lib/thin/version.rb
|
74
85
|
- lib/thin.rb
|
75
|
-
-
|
86
|
+
- lib/thin_parser.so
|
76
87
|
- spec/command_spec.rb
|
88
|
+
- spec/configs
|
89
|
+
- spec/configs/cluster.yml
|
90
|
+
- spec/configs/single.yml
|
91
|
+
- spec/controllers
|
92
|
+
- spec/controllers/cluster_spec.rb
|
93
|
+
- spec/controllers/controller_spec.rb
|
94
|
+
- spec/controllers/service_spec.rb
|
77
95
|
- spec/daemonizing_spec.rb
|
78
96
|
- spec/headers_spec.rb
|
79
97
|
- spec/rack_rails_spec.rb
|
@@ -132,9 +150,18 @@ files:
|
|
132
150
|
- spec/rails_app/script/process/spawner
|
133
151
|
- spec/rails_app/script/runner
|
134
152
|
- spec/rails_app/script/server
|
135
|
-
- spec/
|
153
|
+
- spec/request
|
154
|
+
- spec/request/mongrel_spec.rb
|
155
|
+
- spec/request/parser_spec.rb
|
156
|
+
- spec/request/perf_spec.rb
|
157
|
+
- spec/request/processing_spec.rb
|
136
158
|
- spec/response_spec.rb
|
137
|
-
- spec/
|
159
|
+
- spec/runner_spec.rb
|
160
|
+
- spec/server
|
161
|
+
- spec/server/builder_spec.rb
|
162
|
+
- spec/server/stopping_spec.rb
|
163
|
+
- spec/server/tcp_spec.rb
|
164
|
+
- spec/server/unix_socket_spec.rb
|
138
165
|
- spec/spec_helper.rb
|
139
166
|
- tasks/announce.rake
|
140
167
|
- tasks/deploy.rake
|
@@ -152,7 +179,6 @@ files:
|
|
152
179
|
- ext/thin_parser/extconf.rb
|
153
180
|
- ext/thin_parser/common.rl
|
154
181
|
- ext/thin_parser/parser.rl
|
155
|
-
- lib/thin_parser.so
|
156
182
|
has_rdoc: false
|
157
183
|
homepage: http://code.macournoyer.com/thin/
|
158
184
|
post_install_message:
|