thin 1.8.2 → 2.0.0.pre

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.

Files changed (108) hide show
  1. data/.gitignore +9 -0
  2. data/CHANGELOG +29 -116
  3. data/Gemfile +8 -0
  4. data/README.md +44 -78
  5. data/Rakefile +28 -18
  6. data/bin/thin +4 -4
  7. data/examples/async.ru +21 -0
  8. data/examples/thin.conf.rb +39 -0
  9. data/lib/thin/async.rb +108 -0
  10. data/lib/thin/backends/prefork.rb +44 -0
  11. data/lib/thin/backends/single_process.rb +28 -0
  12. data/lib/thin/chunked_body.rb +28 -0
  13. data/lib/thin/configurator.rb +118 -0
  14. data/lib/thin/connection.rb +246 -172
  15. data/lib/thin/listener.rb +114 -0
  16. data/lib/thin/request.rb +94 -76
  17. data/lib/thin/response.rb +112 -45
  18. data/lib/thin/runner.rb +134 -197
  19. data/lib/thin/server.rb +203 -252
  20. data/lib/thin/system.rb +49 -0
  21. data/lib/thin/version.rb +12 -27
  22. data/lib/thin.rb +2 -44
  23. data/man/index.txt +3 -0
  24. data/man/thin-conf.5.ronn +121 -0
  25. data/man/thin.1.ronn +105 -0
  26. data/site/.gitignore +2 -0
  27. data/site/README.md +21 -0
  28. data/site/Rakefile +20 -0
  29. data/site/config.ru +4 -0
  30. data/site/public/images/grid.png +0 -0
  31. data/site/public/javascripts/dd_belatedpng.js +13 -0
  32. data/site/public/javascripts/modernizr-1.6.min.js +30 -0
  33. data/site/public/man/thin-conf.5.html +220 -0
  34. data/site/public/man/thin.1.html +177 -0
  35. data/site/site/assets/javascripts/main.coffee +2 -0
  36. data/site/site/assets/stylesheets/_config.scss +55 -0
  37. data/site/site/assets/stylesheets/main.scss +24 -0
  38. data/site/site/helpers.rb +17 -0
  39. data/site/site/layouts/base.erb +55 -0
  40. data/site/site/layouts/default.erb +17 -0
  41. data/site/site/pages/about.md +5 -0
  42. data/site/site/pages/index.erb +10 -0
  43. data/site/site/partials/.gitkeep +0 -0
  44. data/test/fixtures/big.txt +1 -0
  45. data/test/fixtures/small.txt +1 -0
  46. data/test/fixtures/thin.conf.rb +15 -0
  47. data/test/integration/async_test.rb +35 -0
  48. data/test/integration/big_request_test.rb +30 -0
  49. data/test/integration/config.ru +57 -0
  50. data/test/integration/daemonize_test.rb +26 -0
  51. data/test/integration/env_test.rb +44 -0
  52. data/test/integration/error_test.rb +37 -0
  53. data/test/integration/file_sending_test.rb +24 -0
  54. data/test/integration/keep_alive_test.rb +35 -0
  55. data/test/integration/robustness_test.rb +37 -0
  56. data/test/integration/single_process_test.rb +15 -0
  57. data/test/integration/socket_family_test.rb +38 -0
  58. data/test/integration/worker_test.rb +22 -0
  59. data/test/test_helper.rb +195 -0
  60. data/test/unit/configurator_test.rb +43 -0
  61. data/test/unit/connection_test.rb +94 -0
  62. data/test/unit/listener_test.rb +74 -0
  63. data/test/unit/request_test.rb +74 -0
  64. data/test/unit/response_test.rb +90 -0
  65. data/test/unit/server_test.rb +29 -0
  66. data/test/unit/system_test.rb +17 -0
  67. data/thin.gemspec +26 -0
  68. data/v2.todo +21 -0
  69. metadata +138 -93
  70. checksums.yaml +0 -7
  71. data/example/adapter.rb +0 -32
  72. data/example/async_app.ru +0 -126
  73. data/example/async_chat.ru +0 -247
  74. data/example/async_tailer.ru +0 -100
  75. data/example/config.ru +0 -22
  76. data/example/monit_sockets +0 -20
  77. data/example/monit_unixsock +0 -20
  78. data/example/myapp.rb +0 -1
  79. data/example/ramaze.ru +0 -12
  80. data/example/thin.god +0 -80
  81. data/example/thin_solaris_smf.erb +0 -36
  82. data/example/thin_solaris_smf.readme.txt +0 -150
  83. data/example/vlad.rake +0 -72
  84. data/ext/thin_parser/common.rl +0 -59
  85. data/ext/thin_parser/ext_help.h +0 -14
  86. data/ext/thin_parser/extconf.rb +0 -6
  87. data/ext/thin_parser/parser.c +0 -1447
  88. data/ext/thin_parser/parser.h +0 -49
  89. data/ext/thin_parser/parser.rl +0 -152
  90. data/ext/thin_parser/thin.c +0 -435
  91. data/lib/rack/adapter/loader.rb +0 -75
  92. data/lib/rack/adapter/rails.rb +0 -178
  93. data/lib/rack/handler/thin.rb +0 -38
  94. data/lib/thin/backends/base.rb +0 -169
  95. data/lib/thin/backends/swiftiply_client.rb +0 -66
  96. data/lib/thin/backends/tcp_server.rb +0 -34
  97. data/lib/thin/backends/unix_server.rb +0 -56
  98. data/lib/thin/command.rb +0 -53
  99. data/lib/thin/controllers/cluster.rb +0 -178
  100. data/lib/thin/controllers/controller.rb +0 -189
  101. data/lib/thin/controllers/service.rb +0 -76
  102. data/lib/thin/controllers/service.sh.erb +0 -39
  103. data/lib/thin/daemonizing.rb +0 -199
  104. data/lib/thin/headers.rb +0 -47
  105. data/lib/thin/logging.rb +0 -174
  106. data/lib/thin/stats.html.erb +0 -216
  107. data/lib/thin/stats.rb +0 -52
  108. data/lib/thin/statuses.rb +0 -48
@@ -0,0 +1,90 @@
1
+ require 'test_helper'
2
+ require 'thin/response'
3
+
4
+ class ResponseTest < Test::Unit::TestCase
5
+ def setup
6
+ @response = Thin::Response.new
7
+ @response.headers['Content-Type'] = 'text/html'
8
+ @response.headers['Content-Length'] = '0'
9
+ @response.body = ''
10
+ @response.finish
11
+ end
12
+
13
+ def test_initialize_with_values
14
+ @response = Thin::Response.new(201, {"Content-Type" => "text/plain"}, ["hi"])
15
+ assert_equal 201, @response.status
16
+ assert_match "Content-Type: text/plain", @response.headers.to_s
17
+ assert_equal ["hi"], @response.body
18
+ end
19
+
20
+ def test_output_headers
21
+ assert_match "Content-Type: text/html", @response.headers.to_s
22
+ assert_match "Content-Length: 0", @response.headers.to_s
23
+ assert_match "Connection: close", @response.headers.to_s
24
+ end
25
+
26
+ def test_include_server_name_header
27
+ assert_match "Server: thin", @response.headers.to_s
28
+ end
29
+
30
+ def test_output_head
31
+ assert_match /^HTTP\/1.1 200 OK/, @response.head
32
+ assert_match /\r\n\r\n$/, @response.head
33
+ end
34
+
35
+ def test_allow_duplicates_on_some_headers
36
+ @response.headers['Set-Cookie'] = 'mium=7'
37
+ @response.headers['Set-Cookie'] = 'hi=there'
38
+
39
+ assert_match "Set-Cookie: mium=7", @response.head
40
+ assert_match "Set-Cookie: hi=there", @response.head
41
+ end
42
+
43
+ def test_parse_simple_header_values
44
+ @response.headers = {
45
+ 'Host' => 'localhost'
46
+ }
47
+
48
+ assert_match "Host: localhost", @response.head
49
+ end
50
+
51
+ def test_parse_multiline_header_values_in_several_headers
52
+ @response.headers = {
53
+ 'Set-Cookie' => "mium=7\nhi=there"
54
+ }
55
+
56
+ assert_match "Set-Cookie: mium=7", @response.head
57
+ assert_match "Set-Cookie: hi=there", @response.head
58
+ end
59
+
60
+ def test_ignore__nil_headers
61
+ @response.headers = nil
62
+ @response.headers = { 'Host' => 'localhost' }
63
+ @response.headers = { 'Set-Cookie' => nil }
64
+ assert_no_match /Set-Cookie/, @response.head
65
+ end
66
+
67
+ def test_body
68
+ @response.body = ['<html>', '</html>']
69
+
70
+ out = ''
71
+ @response.each { |l| out << l }
72
+ assert_match /\r\n\r\n<html><\/html>$/, out
73
+ end
74
+
75
+ def test_string_body
76
+ @response.body = '<html></html>'
77
+
78
+ out = ''
79
+ @response.each { |l| out << l }
80
+ assert_match /\r\n\r\n<html><\/html>$/, out
81
+ end
82
+
83
+ def test_close
84
+ @response.close
85
+ end
86
+
87
+ def test_async
88
+ assert Thin::Response.new(*Thin::Response::ASYNC).async?
89
+ end
90
+ end
@@ -0,0 +1,29 @@
1
+ require 'test_helper'
2
+
3
+ class ServerTest < Test::Unit::TestCase
4
+ def setup
5
+ app = proc { |env| [200, {}, ["ok"]] }
6
+ @server = Thin::Server.new { app }
7
+ end
8
+
9
+ def test_pick_prefork_backend_if_any_workers
10
+ @server.worker_processes = 1
11
+ assert_kind_of Thin::Backends::Prefork, @server.backend
12
+ end
13
+
14
+ def test_pick_single_process_backend_if_no_workers
15
+ @server.worker_processes = 0
16
+ assert_kind_of Thin::Backends::SingleProcess, @server.backend
17
+ end
18
+
19
+ def test_cant_daemonize_single_process
20
+ @server.worker_processes = 0
21
+ assert_raise(NotImplementedError) do
22
+ silence_streams { @server.start(true) }
23
+ end
24
+ end
25
+
26
+ def test_do_not_preload_app
27
+ Thin::Server.new { fail "Should not load app before starting" }
28
+ end
29
+ end
@@ -0,0 +1,17 @@
1
+ require 'test_helper'
2
+
3
+ class SystemTest < Test::Unit::TestCase
4
+ def test_processor_count
5
+ assert_not_equal 0, Thin::System.processor_count
6
+ end
7
+
8
+ if Thin::System.java? || Thin::System.win?
9
+ def test_should_not_support_fork
10
+ assert ! Thin::System.supports_fork?
11
+ end
12
+ else
13
+ def test_should_support_fork
14
+ assert Thin::System.supports_fork?
15
+ end
16
+ end
17
+ end
data/thin.gemspec ADDED
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "thin/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "thin"
7
+ s.version = Thin::VERSION::STRING
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Marc-Andre Cournoyer"]
10
+ s.email = ["thin@macournoyer.com"]
11
+ s.homepage = "http://code.macournoyer.com/thin"
12
+ s.summary = %q{A thin and fast web server}
13
+ s.description = %q{Thin is a Rack based, high performance web server}
14
+
15
+ s.rubyforge_project = "thin"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+
22
+ s.add_dependency "eventmachine-le", "~> 1.1.0"
23
+ s.add_dependency "http_parser.rb", "~> 0.5.3"
24
+ s.add_dependency "preforker", "~> 0.1.1"
25
+ s.add_dependency "rack", "~> 1.4"
26
+ end
data/v2.todo ADDED
@@ -0,0 +1,21 @@
1
+ x prefork
2
+ x listen on UNIX sockets
3
+ x Config
4
+ x Async
5
+ x Preload app
6
+ x Fast file serving with streaming
7
+ x Keep-alive
8
+ x Limit # of keep-alive requests
9
+ - Pipelining?
10
+ x Transfer-Encoding: chunked
11
+ - Use Logger
12
+ - Rotate logs on USR1 signal
13
+ - Zero downtime restart on USR2 signal
14
+ x Threading
15
+ - Change user:group after bind
16
+ - SSL
17
+ - Graceful stop
18
+ - Daemonizing
19
+
20
+ Optimizations:
21
+ - Stock 200 OK response (store in frozen const)
metadata CHANGED
@@ -1,156 +1,201 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: thin
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.8.2
4
+ version: 2.0.0.pre
5
+ prerelease: 6
5
6
  platform: ruby
6
7
  authors:
7
8
  - Marc-Andre Cournoyer
8
- autorequire:
9
+ autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2023-03-31 00:00:00.000000000 Z
12
+ date: 2012-08-10 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
- name: rack
15
+ name: eventmachine-le
15
16
  requirement: !ruby/object:Gem::Requirement
17
+ none: false
16
18
  requirements:
17
- - - ">="
18
- - !ruby/object:Gem::Version
19
- version: '1'
20
- - - "<"
19
+ - - ~>
21
20
  - !ruby/object:Gem::Version
22
- version: '3'
21
+ version: 1.1.0
23
22
  type: :runtime
24
23
  prerelease: false
25
24
  version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
26
  requirements:
27
- - - ">="
28
- - !ruby/object:Gem::Version
29
- version: '1'
30
- - - "<"
27
+ - - ~>
31
28
  - !ruby/object:Gem::Version
32
- version: '3'
29
+ version: 1.1.0
33
30
  - !ruby/object:Gem::Dependency
34
- name: eventmachine
31
+ name: http_parser.rb
35
32
  requirement: !ruby/object:Gem::Requirement
33
+ none: false
36
34
  requirements:
37
- - - "~>"
35
+ - - ~>
38
36
  - !ruby/object:Gem::Version
39
- version: '1.0'
40
- - - ">="
41
- - !ruby/object:Gem::Version
42
- version: 1.0.4
37
+ version: 0.5.3
43
38
  type: :runtime
44
39
  prerelease: false
45
40
  version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
46
42
  requirements:
47
- - - "~>"
48
- - !ruby/object:Gem::Version
49
- version: '1.0'
50
- - - ">="
43
+ - - ~>
51
44
  - !ruby/object:Gem::Version
52
- version: 1.0.4
45
+ version: 0.5.3
53
46
  - !ruby/object:Gem::Dependency
54
- name: daemons
47
+ name: preforker
55
48
  requirement: !ruby/object:Gem::Requirement
49
+ none: false
56
50
  requirements:
57
- - - "~>"
51
+ - - ~>
58
52
  - !ruby/object:Gem::Version
59
- version: '1.0'
60
- - - ">="
61
- - !ruby/object:Gem::Version
62
- version: 1.0.9
53
+ version: 0.1.1
63
54
  type: :runtime
64
55
  prerelease: false
65
56
  version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
66
58
  requirements:
67
- - - "~>"
59
+ - - ~>
68
60
  - !ruby/object:Gem::Version
69
- version: '1.0'
70
- - - ">="
61
+ version: 0.1.1
62
+ - !ruby/object:Gem::Dependency
63
+ name: rack
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: '1.4'
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
71
76
  - !ruby/object:Gem::Version
72
- version: 1.0.9
73
- description:
74
- email: macournoyer@gmail.com
77
+ version: '1.4'
78
+ description: Thin is a Rack based, high performance web server
79
+ email:
80
+ - thin@macournoyer.com
75
81
  executables:
76
82
  - thin
77
- extensions:
78
- - ext/thin_parser/extconf.rb
83
+ extensions: []
79
84
  extra_rdoc_files: []
80
85
  files:
86
+ - .gitignore
81
87
  - CHANGELOG
88
+ - Gemfile
82
89
  - README.md
83
90
  - Rakefile
84
91
  - bin/thin
85
- - example/adapter.rb
86
- - example/async_app.ru
87
- - example/async_chat.ru
88
- - example/async_tailer.ru
89
- - example/config.ru
90
- - example/monit_sockets
91
- - example/monit_unixsock
92
- - example/myapp.rb
93
- - example/ramaze.ru
94
- - example/thin.god
95
- - example/thin_solaris_smf.erb
96
- - example/thin_solaris_smf.readme.txt
97
- - example/vlad.rake
98
- - ext/thin_parser/common.rl
99
- - ext/thin_parser/ext_help.h
100
- - ext/thin_parser/extconf.rb
101
- - ext/thin_parser/parser.c
102
- - ext/thin_parser/parser.h
103
- - ext/thin_parser/parser.rl
104
- - ext/thin_parser/thin.c
105
- - lib/rack/adapter/loader.rb
106
- - lib/rack/adapter/rails.rb
107
- - lib/rack/handler/thin.rb
92
+ - examples/async.ru
93
+ - examples/thin.conf.rb
108
94
  - lib/thin.rb
109
- - lib/thin/backends/base.rb
110
- - lib/thin/backends/swiftiply_client.rb
111
- - lib/thin/backends/tcp_server.rb
112
- - lib/thin/backends/unix_server.rb
113
- - lib/thin/command.rb
95
+ - lib/thin/async.rb
96
+ - lib/thin/backends/prefork.rb
97
+ - lib/thin/backends/single_process.rb
98
+ - lib/thin/chunked_body.rb
99
+ - lib/thin/configurator.rb
114
100
  - lib/thin/connection.rb
115
- - lib/thin/controllers/cluster.rb
116
- - lib/thin/controllers/controller.rb
117
- - lib/thin/controllers/service.rb
118
- - lib/thin/controllers/service.sh.erb
119
- - lib/thin/daemonizing.rb
120
- - lib/thin/headers.rb
121
- - lib/thin/logging.rb
101
+ - lib/thin/listener.rb
122
102
  - lib/thin/request.rb
123
103
  - lib/thin/response.rb
124
104
  - lib/thin/runner.rb
125
105
  - lib/thin/server.rb
126
- - lib/thin/stats.html.erb
127
- - lib/thin/stats.rb
128
- - lib/thin/statuses.rb
106
+ - lib/thin/system.rb
129
107
  - lib/thin/version.rb
130
- homepage: https://github.com/macournoyer/thin
131
- licenses:
132
- - GPL-2.0+
133
- - Ruby
134
- metadata:
135
- source_code_uri: https://github.com/macournoyer/thin
136
- changelog_uri: https://github.com/macournoyer/thin/blob/master/CHANGELOG
137
- post_install_message:
108
+ - man/index.txt
109
+ - man/thin-conf.5.ronn
110
+ - man/thin.1.ronn
111
+ - site/.gitignore
112
+ - site/README.md
113
+ - site/Rakefile
114
+ - site/config.ru
115
+ - site/public/images/grid.png
116
+ - site/public/javascripts/dd_belatedpng.js
117
+ - site/public/javascripts/modernizr-1.6.min.js
118
+ - site/public/man/thin-conf.5.html
119
+ - site/public/man/thin.1.html
120
+ - site/site/assets/javascripts/main.coffee
121
+ - site/site/assets/stylesheets/_config.scss
122
+ - site/site/assets/stylesheets/main.scss
123
+ - site/site/helpers.rb
124
+ - site/site/layouts/base.erb
125
+ - site/site/layouts/default.erb
126
+ - site/site/pages/about.md
127
+ - site/site/pages/index.erb
128
+ - site/site/partials/.gitkeep
129
+ - test/fixtures/big.txt
130
+ - test/fixtures/small.txt
131
+ - test/fixtures/thin.conf.rb
132
+ - test/integration/async_test.rb
133
+ - test/integration/big_request_test.rb
134
+ - test/integration/config.ru
135
+ - test/integration/daemonize_test.rb
136
+ - test/integration/env_test.rb
137
+ - test/integration/error_test.rb
138
+ - test/integration/file_sending_test.rb
139
+ - test/integration/keep_alive_test.rb
140
+ - test/integration/robustness_test.rb
141
+ - test/integration/single_process_test.rb
142
+ - test/integration/socket_family_test.rb
143
+ - test/integration/worker_test.rb
144
+ - test/test_helper.rb
145
+ - test/unit/configurator_test.rb
146
+ - test/unit/connection_test.rb
147
+ - test/unit/listener_test.rb
148
+ - test/unit/request_test.rb
149
+ - test/unit/response_test.rb
150
+ - test/unit/server_test.rb
151
+ - test/unit/system_test.rb
152
+ - thin.gemspec
153
+ - v2.todo
154
+ homepage: http://code.macournoyer.com/thin
155
+ licenses: []
156
+ post_install_message:
138
157
  rdoc_options: []
139
158
  require_paths:
140
159
  - lib
141
160
  required_ruby_version: !ruby/object:Gem::Requirement
161
+ none: false
142
162
  requirements:
143
- - - ">="
163
+ - - ! '>='
144
164
  - !ruby/object:Gem::Version
145
- version: 1.8.5
165
+ version: '0'
146
166
  required_rubygems_version: !ruby/object:Gem::Requirement
167
+ none: false
147
168
  requirements:
148
- - - ">="
169
+ - - ! '>'
149
170
  - !ruby/object:Gem::Version
150
- version: '0'
171
+ version: 1.3.1
151
172
  requirements: []
152
- rubygems_version: 3.4.7
153
- signing_key:
154
- specification_version: 4
173
+ rubyforge_project: thin
174
+ rubygems_version: 1.8.24
175
+ signing_key:
176
+ specification_version: 3
155
177
  summary: A thin and fast web server
156
- test_files: []
178
+ test_files:
179
+ - test/fixtures/big.txt
180
+ - test/fixtures/small.txt
181
+ - test/fixtures/thin.conf.rb
182
+ - test/integration/async_test.rb
183
+ - test/integration/big_request_test.rb
184
+ - test/integration/config.ru
185
+ - test/integration/daemonize_test.rb
186
+ - test/integration/env_test.rb
187
+ - test/integration/error_test.rb
188
+ - test/integration/file_sending_test.rb
189
+ - test/integration/keep_alive_test.rb
190
+ - test/integration/robustness_test.rb
191
+ - test/integration/single_process_test.rb
192
+ - test/integration/socket_family_test.rb
193
+ - test/integration/worker_test.rb
194
+ - test/test_helper.rb
195
+ - test/unit/configurator_test.rb
196
+ - test/unit/connection_test.rb
197
+ - test/unit/listener_test.rb
198
+ - test/unit/request_test.rb
199
+ - test/unit/response_test.rb
200
+ - test/unit/server_test.rb
201
+ - test/unit/system_test.rb
checksums.yaml DELETED
@@ -1,7 +0,0 @@
1
- ---
2
- SHA256:
3
- metadata.gz: 32913c8b29b57b8f15fcd7cffb49db757989a225794e089ced01e53354c3cd90
4
- data.tar.gz: f232efe452f20785ea8e71422a53147205ffd65ddbba90b8ba12e5b340c3b466
5
- SHA512:
6
- metadata.gz: 2cf9f7764e73b4086d1a11156bcd1aa67e6e3cabc32076e404971f866e3d4f28b536375773d03bf54e8237d3755cb70399c421044cb7cb577801f2f1deefe4d8
7
- data.tar.gz: ed2643e1bc850bea3bd868150cd5c6b198b440b585a99def2099c35122d7a663c928c508f7441c4d708df6c878296b0e5cafcf9ebcfe70ef6ac6a1ca645111fe
data/example/adapter.rb DELETED
@@ -1,32 +0,0 @@
1
- # Run with: ruby adapter.rb
2
- # Then browse to http://localhost:3000/test
3
- # and http://localhost:3000/files/adapter.rb
4
- require 'thin'
5
-
6
- class SimpleAdapter
7
- def call(env)
8
- body = ["hello!"]
9
- [
10
- 200,
11
- { 'Content-Type' => 'text/plain' },
12
- body
13
- ]
14
- end
15
- end
16
-
17
- Thin::Server.start('0.0.0.0', 3000) do
18
- use Rack::CommonLogger
19
- map '/test' do
20
- run SimpleAdapter.new
21
- end
22
- map '/files' do
23
- run Rack::File.new('.')
24
- end
25
- end
26
-
27
- # You could also start the server like this:
28
- #
29
- # app = Rack::URLMap.new('/test' => SimpleAdapter.new,
30
- # '/files' => Rack::File.new('.'))
31
- # Thin::Server.start('0.0.0.0', 3000, app)
32
- #
data/example/async_app.ru DELETED
@@ -1,126 +0,0 @@
1
- #!/usr/bin/env rackup -s thin
2
- #
3
- # async_app.ru
4
- # raggi/thin
5
- #
6
- # A second demo app for async rack + thin app processing!
7
- # Now using http status code 100 instead.
8
- #
9
- # Created by James Tucker on 2008-06-17.
10
- # Copyright 2008 James Tucker <raggi@rubyforge.org>.
11
- #
12
- #--
13
- # Benchmark Results:
14
- #
15
- # raggi@mbk:~$ ab -c 100 -n 500 http://127.0.0.1:3000/
16
- # This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0
17
- # Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
18
- # Copyright 2006 The Apache Software Foundation, http://www.apache.org/
19
- #
20
- # Benchmarking 127.0.0.1 (be patient)
21
- # Completed 100 requests
22
- # Completed 200 requests
23
- # Completed 300 requests
24
- # Completed 400 requests
25
- # Finished 500 requests
26
- #
27
- #
28
- # Server Software: thin
29
- # Server Hostname: 127.0.0.1
30
- # Server Port: 3000
31
- #
32
- # Document Path: /
33
- # Document Length: 12 bytes
34
- #
35
- # Concurrency Level: 100
36
- # Time taken for tests: 5.263089 seconds
37
- # Complete requests: 500
38
- # Failed requests: 0
39
- # Write errors: 0
40
- # Total transferred: 47000 bytes
41
- # HTML transferred: 6000 bytes
42
- # Requests per second: 95.00 [#/sec] (mean)
43
- # Time per request: 1052.618 [ms] (mean)
44
- # Time per request: 10.526 [ms] (mean, across all concurrent requests)
45
- # Transfer rate: 8.55 [Kbytes/sec] received
46
- #
47
- # Connection Times (ms)
48
- # min mean[+/-sd] median max
49
- # Connect: 0 3 2.2 3 8
50
- # Processing: 1042 1046 3.1 1046 1053
51
- # Waiting: 1037 1042 3.6 1041 1050
52
- # Total: 1045 1049 3.1 1049 1057
53
- #
54
- # Percentage of the requests served within a certain time (ms)
55
- # 50% 1049
56
- # 66% 1051
57
- # 75% 1053
58
- # 80% 1053
59
- # 90% 1054
60
- # 95% 1054
61
- # 98% 1056
62
- # 99% 1057
63
- # 100% 1057 (longest request)
64
-
65
- class DeferrableBody
66
- include EventMachine::Deferrable
67
-
68
- def call(body)
69
- body.each do |chunk|
70
- @body_callback.call(chunk)
71
- end
72
- end
73
-
74
- def each &blk
75
- @body_callback = blk
76
- end
77
-
78
- end
79
-
80
- class AsyncApp
81
-
82
- # This is a template async response. N.B. Can't use string for body on 1.9
83
- AsyncResponse = [-1, {}, []].freeze
84
-
85
- def call(env)
86
-
87
- body = DeferrableBody.new
88
-
89
- # Get the headers out there asap, let the client know we're alive...
90
- EventMachine::next_tick { env['async.callback'].call [200, {'Content-Type' => 'text/plain'}, body] }
91
-
92
- # Semi-emulate a long db request, instead of a timer, in reality we'd be
93
- # waiting for the response data. Whilst this happens, other connections
94
- # can be serviced.
95
- # This could be any callback based thing though, a deferrable waiting on
96
- # IO data, a db request, an http request, an smtp send, whatever.
97
- EventMachine::add_timer(1) {
98
- body.call ["Woah, async!\n"]
99
-
100
- EventMachine::next_tick {
101
- # This could actually happen any time, you could spawn off to new
102
- # threads, pause as a good looking lady walks by, whatever.
103
- # Just shows off how we can defer chunks of data in the body, you can
104
- # even call this many times.
105
- body.call ["Cheers then!"]
106
- body.succeed
107
- }
108
- }
109
-
110
- # throw :async # Still works for supporting non-async frameworks...
111
-
112
- AsyncResponse # May end up in Rack :-)
113
- end
114
-
115
- end
116
-
117
- # The additions to env for async.connection and async.callback absolutely
118
- # destroy the speed of the request if Lint is doing it's checks on env.
119
- # It is also important to note that an async response will not pass through
120
- # any further middleware, as the async response notification has been passed
121
- # right up to the webserver, and the callback goes directly there too.
122
- # Middleware could possibly catch :async, and also provide a different
123
- # async.connection and async.callback.
124
-
125
- # use Rack::Lint
126
- run AsyncApp.new