thin 1.3.1 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. data/CHANGELOG +8 -0
  2. data/README.md +83 -0
  3. data/Rakefile +9 -32
  4. data/example/vlad.rake +1 -1
  5. data/lib/rack/adapter/loader.rb +0 -16
  6. data/lib/thin.rb +22 -24
  7. data/lib/thin/backends/base.rb +3 -1
  8. data/lib/thin/connection.rb +9 -8
  9. data/lib/thin/daemonizing.rb +3 -1
  10. data/lib/thin/logging.rb +1 -1
  11. data/lib/thin/runner.rb +36 -36
  12. data/lib/thin/server.rb +13 -0
  13. data/lib/thin/version.rb +3 -3
  14. metadata +5 -91
  15. data/README +0 -69
  16. data/benchmark/abc +0 -51
  17. data/benchmark/benchmarker.rb +0 -80
  18. data/benchmark/runner +0 -82
  19. data/spec/backends/swiftiply_client_spec.rb +0 -66
  20. data/spec/backends/tcp_server_spec.rb +0 -33
  21. data/spec/backends/unix_server_spec.rb +0 -37
  22. data/spec/command_spec.rb +0 -25
  23. data/spec/configs/cluster.yml +0 -9
  24. data/spec/configs/single.yml +0 -9
  25. data/spec/connection_spec.rb +0 -107
  26. data/spec/controllers/cluster_spec.rb +0 -267
  27. data/spec/controllers/controller_spec.rb +0 -129
  28. data/spec/controllers/service_spec.rb +0 -50
  29. data/spec/daemonizing_spec.rb +0 -200
  30. data/spec/headers_spec.rb +0 -40
  31. data/spec/logging_spec.rb +0 -52
  32. data/spec/perf/request_perf_spec.rb +0 -50
  33. data/spec/perf/response_perf_spec.rb +0 -19
  34. data/spec/perf/server_perf_spec.rb +0 -39
  35. data/spec/rack/loader_spec.rb +0 -42
  36. data/spec/rack/rails_adapter_spec.rb +0 -173
  37. data/spec/rails_app/app/controllers/application.rb +0 -10
  38. data/spec/rails_app/app/controllers/simple_controller.rb +0 -19
  39. data/spec/rails_app/app/helpers/application_helper.rb +0 -3
  40. data/spec/rails_app/app/views/simple/index.html.erb +0 -15
  41. data/spec/rails_app/config/boot.rb +0 -109
  42. data/spec/rails_app/config/environment.rb +0 -64
  43. data/spec/rails_app/config/environments/development.rb +0 -18
  44. data/spec/rails_app/config/environments/production.rb +0 -19
  45. data/spec/rails_app/config/environments/test.rb +0 -22
  46. data/spec/rails_app/config/initializers/inflections.rb +0 -10
  47. data/spec/rails_app/config/initializers/mime_types.rb +0 -5
  48. data/spec/rails_app/config/routes.rb +0 -35
  49. data/spec/rails_app/public/404.html +0 -30
  50. data/spec/rails_app/public/422.html +0 -30
  51. data/spec/rails_app/public/500.html +0 -30
  52. data/spec/rails_app/public/dispatch.cgi +0 -10
  53. data/spec/rails_app/public/dispatch.fcgi +0 -24
  54. data/spec/rails_app/public/dispatch.rb +0 -10
  55. data/spec/rails_app/public/favicon.ico +0 -0
  56. data/spec/rails_app/public/images/rails.png +0 -0
  57. data/spec/rails_app/public/index.html +0 -277
  58. data/spec/rails_app/public/javascripts/application.js +0 -2
  59. data/spec/rails_app/public/javascripts/controls.js +0 -963
  60. data/spec/rails_app/public/javascripts/dragdrop.js +0 -972
  61. data/spec/rails_app/public/javascripts/effects.js +0 -1120
  62. data/spec/rails_app/public/javascripts/prototype.js +0 -4225
  63. data/spec/rails_app/public/robots.txt +0 -5
  64. data/spec/rails_app/script/about +0 -3
  65. data/spec/rails_app/script/console +0 -3
  66. data/spec/rails_app/script/destroy +0 -3
  67. data/spec/rails_app/script/generate +0 -3
  68. data/spec/rails_app/script/performance/benchmarker +0 -3
  69. data/spec/rails_app/script/performance/profiler +0 -3
  70. data/spec/rails_app/script/performance/request +0 -3
  71. data/spec/rails_app/script/plugin +0 -3
  72. data/spec/rails_app/script/process/inspector +0 -3
  73. data/spec/rails_app/script/process/reaper +0 -3
  74. data/spec/rails_app/script/process/spawner +0 -3
  75. data/spec/rails_app/script/runner +0 -3
  76. data/spec/rails_app/script/server +0 -3
  77. data/spec/request/mongrel_spec.rb +0 -39
  78. data/spec/request/parser_spec.rb +0 -254
  79. data/spec/request/persistent_spec.rb +0 -35
  80. data/spec/request/processing_spec.rb +0 -50
  81. data/spec/response_spec.rb +0 -102
  82. data/spec/runner_spec.rb +0 -168
  83. data/spec/server/builder_spec.rb +0 -44
  84. data/spec/server/pipelining_spec.rb +0 -110
  85. data/spec/server/robustness_spec.rb +0 -34
  86. data/spec/server/stopping_spec.rb +0 -55
  87. data/spec/server/swiftiply.yml +0 -6
  88. data/spec/server/swiftiply_spec.rb +0 -32
  89. data/spec/server/tcp_spec.rb +0 -47
  90. data/spec/server/threaded_spec.rb +0 -27
  91. data/spec/server/unix_socket_spec.rb +0 -26
  92. data/spec/server_spec.rb +0 -100
  93. data/spec/spec_helper.rb +0 -234
  94. data/tasks/announce.rake +0 -22
  95. data/tasks/deploy.rake +0 -13
  96. data/tasks/email.erb +0 -27
  97. data/tasks/gem.rake +0 -65
  98. data/tasks/rdoc.rake +0 -25
  99. data/tasks/site.rake +0 -15
  100. data/tasks/spec.rake +0 -43
  101. data/tasks/stats.rake +0 -28
@@ -1,102 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Response do
4
- before do
5
- @response = Response.new
6
- @response.headers['Content-Type'] = 'text/html'
7
- @response.headers['Content-Length'] = '0'
8
- @response.body = ''
9
- end
10
-
11
- it 'should output headers' do
12
- @response.headers_output.should include("Content-Type: text/html", "Content-Length: 0", "Connection: close")
13
- end
14
-
15
- it 'should include server name header' do
16
- @response.headers_output.should include("Server: thin")
17
- end
18
-
19
- it 'should output head' do
20
- @response.head.should include("HTTP/1.1 200 OK", "Content-Type: text/html", "Content-Length: 0",
21
- "Connection: close", "\r\n\r\n")
22
- end
23
-
24
- it 'should allow duplicates in headers' do
25
- @response.headers['Set-Cookie'] = 'mium=7'
26
- @response.headers['Set-Cookie'] = 'hi=there'
27
-
28
- @response.head.should include("Set-Cookie: mium=7", "Set-Cookie: hi=there")
29
- end
30
-
31
- it 'should parse simple header values' do
32
- @response.headers = {
33
- 'Host' => 'localhost'
34
- }
35
-
36
- @response.head.should include("Host: localhost")
37
- end
38
-
39
- it 'should parse multiline header values in several headers' do
40
- @response.headers = {
41
- 'Set-Cookie' => "mium=7\nhi=there"
42
- }
43
-
44
- @response.head.should include("Set-Cookie: mium=7", "Set-Cookie: hi=there")
45
- end
46
-
47
- it 'should ignore nil headers' do
48
- @response.headers = nil
49
- @response.headers = { 'Host' => 'localhost' }
50
- @response.headers = { 'Set-Cookie' => nil }
51
- @response.head.should include('Host: localhost')
52
- end
53
-
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
63
- @response.body = '<html></html>'
64
-
65
- out = ''
66
- @response.each { |l| out << l }
67
- out.should include("\r\n\r\n<html></html>")
68
- end
69
-
70
- it "should not be persistent by default" do
71
- @response.should_not be_persistent
72
- end
73
-
74
- it "should not be persistent when no Content-Length" do
75
- @response = Response.new
76
- @response.headers['Content-Type'] = 'text/html'
77
- @response.body = ''
78
-
79
- @response.persistent!
80
- @response.should_not be_persistent
81
- end
82
-
83
- it "should be persistent when the status code implies it should stay open" do
84
- @response = Response.new
85
- @response.status = 100
86
- # "There are no required headers for this class of status code" -- HTTP spec 10.1
87
- @response.body = ''
88
-
89
- # Specifying it as persistent in the code is NOT required
90
- # @response.persistent!
91
- @response.should be_persistent
92
- end
93
-
94
- it "should be persistent when specified" do
95
- @response.persistent!
96
- @response.should be_persistent
97
- end
98
-
99
- it "should be closeable" do
100
- @response.close
101
- end
102
- end
@@ -1,168 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Runner do
4
- it "should parse options" do
5
- runner = Runner.new(%w(start --pid test.pid --port 5000 -o 3000))
6
-
7
- runner.options[:pid].should == 'test.pid'
8
- runner.options[:port].should == 5000
9
- runner.options[:only].should == 3000
10
- end
11
-
12
- it "should parse specified command" do
13
- Runner.new(%w(start)).command.should == 'start'
14
- Runner.new(%w(stop)).command.should == 'stop'
15
- Runner.new(%w(restart)).command.should == 'restart'
16
- end
17
-
18
- it "should abort on unknow command" do
19
- runner = Runner.new(%w(poop))
20
-
21
- runner.should_receive(:abort)
22
- runner.run!
23
- end
24
-
25
- it "should exit on empty command" do
26
- runner = Runner.new([])
27
-
28
- runner.should_receive(:exit).with(1)
29
-
30
- silence_stream(STDOUT) do
31
- runner.run!
32
- end
33
- end
34
-
35
- it "should use Controller when controlling a single server" do
36
- runner = Runner.new(%w(start))
37
-
38
- controller = mock('controller')
39
- controller.should_receive(:start)
40
- Controllers::Controller.should_receive(:new).and_return(controller)
41
-
42
- runner.run!
43
- end
44
-
45
- it "should use Cluster controller when controlling multiple servers" do
46
- runner = Runner.new(%w(start --servers 3))
47
-
48
- controller = mock('cluster')
49
- controller.should_receive(:start)
50
- Controllers::Cluster.should_receive(:new).and_return(controller)
51
-
52
- runner.run!
53
- end
54
-
55
- it "should default to single server controller" do
56
- Runner.new(%w(start)).should_not be_a_cluster
57
- end
58
-
59
- it "should consider as a cluster with :servers option" do
60
- Runner.new(%w(start --servers 3)).should be_a_cluster
61
- end
62
-
63
- it "should consider as a cluster with :only option" do
64
- Runner.new(%w(start --only 3000)).should be_a_cluster
65
- end
66
-
67
- it "should warn when require a rack config file" do
68
- STDERR.stub!(:write)
69
- STDERR.should_receive(:write).with(/WARNING:/)
70
-
71
- runner = Runner.new(%w(start -r config.ru))
72
- runner.run! rescue nil
73
-
74
- runner.options[:rackup].should == 'config.ru'
75
- end
76
-
77
- it "should require file" do
78
- runner = Runner.new(%w(start -r unexisting))
79
- proc { runner.run! }.should raise_error(LoadError)
80
- end
81
-
82
- it "should remember requires" do
83
- runner = Runner.new(%w(start -r rubygems -r thin))
84
- runner.options[:require].should == %w(rubygems thin)
85
- end
86
-
87
- it "should remember debug options" do
88
- runner = Runner.new(%w(start -D -V))
89
- runner.options[:debug].should be_true
90
- runner.options[:trace].should be_true
91
- end
92
-
93
- it "should default debug and trace to false" do
94
- runner = Runner.new(%w(start))
95
- runner.options[:debug].should_not be_true
96
- runner.options[:trace].should_not be_true
97
- end
98
- end
99
-
100
- describe Runner, 'with config file' do
101
- before do
102
- @runner = Runner.new(%w(start --config spec/configs/cluster.yml))
103
- end
104
-
105
- it "should load options from file with :config option" do
106
- @runner.send :load_options_from_config_file!
107
-
108
- @runner.options[:environment].should == 'production'
109
- @runner.options[:chdir].should == 'spec/rails_app'
110
- @runner.options[:port].should == 5000
111
- @runner.options[:servers].should == 3
112
- end
113
-
114
- it "should change directory after loading config" do
115
- @orig_dir = Dir.pwd
116
-
117
- controller = mock('controller')
118
- controller.should_receive(:respond_to?).with('start').and_return(true)
119
- controller.should_receive(:start)
120
- Controllers::Cluster.should_receive(:new).and_return(controller)
121
- expected_dir = File.expand_path('spec/rails_app')
122
-
123
- begin
124
- silence_stream(STDERR) do
125
- @runner.run!
126
- end
127
-
128
- Dir.pwd.should == expected_dir
129
-
130
- ensure
131
- # any other spec using relative paths should work as expected
132
- Dir.chdir(@orig_dir)
133
- end
134
- end
135
- end
136
-
137
- describe Runner, "service" do
138
- before do
139
- Thin.stub!(:linux?).and_return(true)
140
-
141
- @controller = mock('service')
142
- Controllers::Service.stub!(:new).and_return(@controller)
143
- end
144
-
145
- it "should use Service controller when controlling all servers" do
146
- runner = Runner.new(%w(start --all))
147
-
148
- @controller.should_receive(:start)
149
-
150
- runner.run!
151
- end
152
-
153
- it "should call install with arguments" do
154
- runner = Runner.new(%w(install /etc/cool))
155
-
156
- @controller.should_receive(:install).with('/etc/cool')
157
-
158
- runner.run!
159
- end
160
-
161
- it "should call install without arguments" do
162
- runner = Runner.new(%w(install))
163
-
164
- @controller.should_receive(:install).with()
165
-
166
- runner.run!
167
- end
168
- end
@@ -1,44 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Server, 'app builder' do
4
- it "should build app from constructor" do
5
- app = proc {}
6
- server = Server.new('0.0.0.0', 3000, app)
7
-
8
- server.app.should == app
9
- end
10
-
11
- it "should build app from builder block" do
12
- server = Server.new '0.0.0.0', 3000 do
13
- run(proc { |env| :works })
14
- end
15
-
16
- server.app.call({}).should == :works
17
- end
18
-
19
- it "should use middlewares in builder block" do
20
- server = Server.new '0.0.0.0', 3000 do
21
- use Rack::ShowExceptions
22
- run(proc { |env| :works })
23
- end
24
-
25
- server.app.class.should == Rack::ShowExceptions
26
- server.app.call({}).should == :works
27
- end
28
-
29
- it "should work with Rack url mapper" do
30
- server = Server.new '0.0.0.0', 3000 do
31
- map '/test' do
32
- run(proc { |env| [200, {}, 'Found /test'] })
33
- end
34
- end
35
-
36
- default_env = { 'SCRIPT_NAME' => '' }
37
-
38
- server.app.call(default_env.update('PATH_INFO' => '/'))[0].should == 404
39
-
40
- status, headers, body = server.app.call(default_env.update('PATH_INFO' => '/test'))
41
- status.should == 200
42
- body.should == 'Found /test'
43
- end
44
- end
@@ -1,110 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Server, "HTTP pipelining" do
4
- before do
5
- calls = 0
6
- start_server do |env|
7
- calls += 1
8
- body = env['PATH_INFO'] + '-' + calls.to_s
9
- [200, { 'Content-Type' => 'text/html' }, body]
10
- end
11
- @server.maximum_persistent_connections = 1024
12
- end
13
-
14
- it "should pipeline request on same socket" do
15
- socket = TCPSocket.new('0.0.0.0', 3333)
16
- socket.write "GET /first HTTP/1.1\r\nConnection: keep-alive\r\n\r\n"
17
- socket.flush
18
- socket.write "GET /second HTTP/1.1\r\nConnection: close\r\n\r\n"
19
- socket.flush
20
- response = socket.read
21
- socket.close
22
-
23
- wait_for_requests_to_complete!
24
-
25
- response.should include('/first-1', '/second-2')
26
- end
27
-
28
- it "should pipeline requests by default on HTTP 1.1" do
29
- socket = TCPSocket.new('0.0.0.0', 3333)
30
- socket.write "GET /first HTTP/1.1\r\n\r\n"
31
- socket.flush
32
- socket.write "GET /second HTTP/1.1\r\nConnection: close\r\n\r\n"
33
- socket.flush
34
- response = socket.read
35
- socket.close
36
-
37
- wait_for_requests_to_complete!
38
-
39
- response.should include('/first-1', '/second-2')
40
- end
41
-
42
- it "should not pipeline request by default on HTTP 1.0" do
43
- socket = TCPSocket.new('0.0.0.0', 3333)
44
- socket.write "GET /first HTTP/1.0\r\n\r\n"
45
- socket.flush
46
- socket.write "GET /second HTTP/1.0\r\nConnection: close\r\n\r\n"
47
- response = socket.read
48
- socket.close
49
-
50
- wait_for_requests_to_complete!
51
-
52
- response.should include('/first-1')
53
- response.should_not include('/second-2')
54
- end
55
-
56
- it "should not pipeline request on same socket when connection is closed" do
57
- socket = TCPSocket.new('0.0.0.0', 3333)
58
- socket.write "GET /first HTTP/1.1\r\nConnection: close\r\n\r\n"
59
- socket.flush
60
- socket.write "GET /second HTTP/1.1\r\nConnection: close\r\n\r\n"
61
- response = socket.read
62
- socket.close
63
-
64
- wait_for_requests_to_complete!
65
-
66
- response.should include('/first-1')
67
- response.should_not include('/second-2')
68
- end
69
-
70
- it "should not allow more persistent connection then maximum" do
71
- @server.maximum_persistent_connections = 1
72
-
73
- socket1 = TCPSocket.new('0.0.0.0', 3333)
74
- socket1.write "GET / HTTP/1.1\r\n\r\n"
75
- socket1.flush
76
- socket2 = TCPSocket.new('0.0.0.0', 3333)
77
- socket2.write "GET / HTTP/1.1\r\n\r\n"
78
- socket2.flush
79
-
80
- @server.backend.persistent_connection_count.should == 1
81
- @server.backend.size.should == 2
82
-
83
- socket1.close
84
- socket2.close
85
- end
86
-
87
- it "should decrement persistent connection on close" do
88
- socket = TCPSocket.new('0.0.0.0', 3333)
89
- socket.write "GET / HTTP/1.1\r\n\r\n"
90
- socket.flush
91
-
92
- @server.backend.persistent_connection_count.should == 1
93
-
94
- socket.write "GET / HTTP/1.1\r\nConnection: close\r\n\r\n"
95
- socket.close
96
-
97
- wait_for_requests_to_complete!
98
-
99
- @server.backend.persistent_connection_count.should == 0
100
- end
101
-
102
- after do
103
- stop_server
104
- end
105
-
106
- private
107
- def wait_for_requests_to_complete!
108
- sleep 0.1 until @server.backend.size == 0
109
- end
110
- end
@@ -1,34 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Server, 'robustness' do
4
- before do
5
- start_server do |env|
6
- body = 'hello!'
7
- [200, { 'Content-Type' => 'text/html' }, body]
8
- end
9
- end
10
-
11
- it "should not crash when header too large" do
12
- 100.times do
13
- begin
14
- socket = TCPSocket.new(DEFAULT_TEST_ADDRESS, DEFAULT_TEST_PORT)
15
- socket.write("GET / HTTP/1.1\r\n")
16
- socket.write("Host: localhost\r\n")
17
- socket.write("Connection: close\r\n")
18
- 10000.times do
19
- socket.write("X-Foo: #{'x' * 100}\r\n")
20
- socket.flush
21
- end
22
- socket.write("\r\n")
23
- socket.read
24
- socket.close
25
- rescue Errno::EPIPE, Errno::ECONNRESET
26
- # Ignore.
27
- end
28
- end
29
- end
30
-
31
- after do
32
- stop_server
33
- end
34
- end