rack 2.0.3 → 2.2.4

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of rack might be problematic. Click here for more details.

Files changed (190) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +708 -0
  3. data/CONTRIBUTING.md +136 -0
  4. data/{COPYING → MIT-LICENSE} +4 -2
  5. data/README.rdoc +152 -150
  6. data/Rakefile +37 -23
  7. data/{SPEC → SPEC.rdoc} +35 -10
  8. data/bin/rackup +1 -0
  9. data/example/lobster.ru +2 -0
  10. data/example/protectedlobster.rb +3 -1
  11. data/example/protectedlobster.ru +2 -0
  12. data/lib/rack/auth/abstract/handler.rb +3 -1
  13. data/lib/rack/auth/abstract/request.rb +1 -1
  14. data/lib/rack/auth/basic.rb +7 -4
  15. data/lib/rack/auth/digest/md5.rb +13 -11
  16. data/lib/rack/auth/digest/nonce.rb +6 -3
  17. data/lib/rack/auth/digest/params.rb +4 -2
  18. data/lib/rack/auth/digest/request.rb +5 -3
  19. data/lib/rack/body_proxy.rb +15 -14
  20. data/lib/rack/builder.rb +116 -23
  21. data/lib/rack/cascade.rb +28 -12
  22. data/lib/rack/chunked.rb +68 -20
  23. data/lib/rack/common_logger.rb +36 -25
  24. data/lib/rack/conditional_get.rb +20 -16
  25. data/lib/rack/config.rb +2 -0
  26. data/lib/rack/content_length.rb +8 -7
  27. data/lib/rack/content_type.rb +5 -4
  28. data/lib/rack/core_ext/regexp.rb +14 -0
  29. data/lib/rack/deflater.rb +59 -34
  30. data/lib/rack/directory.rb +84 -64
  31. data/lib/rack/etag.rb +8 -5
  32. data/lib/rack/events.rb +19 -20
  33. data/lib/rack/file.rb +4 -173
  34. data/lib/rack/files.rb +218 -0
  35. data/lib/rack/handler/cgi.rb +2 -3
  36. data/lib/rack/handler/fastcgi.rb +4 -4
  37. data/lib/rack/handler/lsws.rb +3 -3
  38. data/lib/rack/handler/scgi.rb +9 -8
  39. data/lib/rack/handler/thin.rb +3 -3
  40. data/lib/rack/handler/webrick.rb +15 -6
  41. data/lib/rack/handler.rb +7 -2
  42. data/lib/rack/head.rb +1 -1
  43. data/lib/rack/lint.rb +72 -26
  44. data/lib/rack/lobster.rb +10 -10
  45. data/lib/rack/lock.rb +14 -4
  46. data/lib/rack/logger.rb +2 -0
  47. data/lib/rack/media_type.rb +10 -5
  48. data/lib/rack/method_override.rb +9 -3
  49. data/lib/rack/mime.rb +9 -1
  50. data/lib/rack/mock.rb +98 -21
  51. data/lib/rack/multipart/generator.rb +17 -13
  52. data/lib/rack/multipart/parser.rb +61 -63
  53. data/lib/rack/multipart/uploaded_file.rb +15 -7
  54. data/lib/rack/multipart.rb +5 -4
  55. data/lib/rack/null_logger.rb +2 -0
  56. data/lib/rack/query_parser.rb +59 -30
  57. data/lib/rack/recursive.rb +7 -5
  58. data/lib/rack/reloader.rb +8 -4
  59. data/lib/rack/request.rb +228 -56
  60. data/lib/rack/response.rb +127 -44
  61. data/lib/rack/rewindable_input.rb +4 -3
  62. data/lib/rack/runtime.rb +6 -4
  63. data/lib/rack/sendfile.rb +13 -9
  64. data/lib/rack/server.rb +95 -24
  65. data/lib/rack/session/abstract/id.rb +100 -22
  66. data/lib/rack/session/cookie.rb +22 -14
  67. data/lib/rack/session/memcache.rb +4 -87
  68. data/lib/rack/session/pool.rb +18 -9
  69. data/lib/rack/show_exceptions.rb +22 -18
  70. data/lib/rack/show_status.rb +9 -9
  71. data/lib/rack/static.rb +23 -11
  72. data/lib/rack/tempfile_reaper.rb +1 -1
  73. data/lib/rack/urlmap.rb +12 -6
  74. data/lib/rack/utils.rb +107 -111
  75. data/lib/rack/version.rb +29 -0
  76. data/lib/rack.rb +67 -73
  77. data/rack.gemspec +40 -29
  78. metadata +25 -181
  79. data/HISTORY.md +0 -505
  80. data/test/builder/an_underscore_app.rb +0 -5
  81. data/test/builder/anything.rb +0 -5
  82. data/test/builder/comment.ru +0 -4
  83. data/test/builder/end.ru +0 -5
  84. data/test/builder/line.ru +0 -1
  85. data/test/builder/options.ru +0 -2
  86. data/test/cgi/assets/folder/test.js +0 -1
  87. data/test/cgi/assets/fonts/font.eot +0 -1
  88. data/test/cgi/assets/images/image.png +0 -1
  89. data/test/cgi/assets/index.html +0 -1
  90. data/test/cgi/assets/javascripts/app.js +0 -1
  91. data/test/cgi/assets/stylesheets/app.css +0 -1
  92. data/test/cgi/lighttpd.conf +0 -26
  93. data/test/cgi/rackup_stub.rb +0 -6
  94. data/test/cgi/sample_rackup.ru +0 -5
  95. data/test/cgi/test +0 -9
  96. data/test/cgi/test+directory/test+file +0 -1
  97. data/test/cgi/test.fcgi +0 -9
  98. data/test/cgi/test.gz +0 -0
  99. data/test/cgi/test.ru +0 -5
  100. data/test/gemloader.rb +0 -10
  101. data/test/helper.rb +0 -34
  102. data/test/multipart/bad_robots +0 -259
  103. data/test/multipart/binary +0 -0
  104. data/test/multipart/content_type_and_no_filename +0 -6
  105. data/test/multipart/empty +0 -10
  106. data/test/multipart/fail_16384_nofile +0 -814
  107. data/test/multipart/file1.txt +0 -1
  108. data/test/multipart/filename_and_modification_param +0 -7
  109. data/test/multipart/filename_and_no_name +0 -6
  110. data/test/multipart/filename_with_encoded_words +0 -7
  111. data/test/multipart/filename_with_escaped_quotes +0 -6
  112. data/test/multipart/filename_with_escaped_quotes_and_modification_param +0 -7
  113. data/test/multipart/filename_with_null_byte +0 -7
  114. data/test/multipart/filename_with_percent_escaped_quotes +0 -6
  115. data/test/multipart/filename_with_single_quote +0 -7
  116. data/test/multipart/filename_with_unescaped_percentages +0 -6
  117. data/test/multipart/filename_with_unescaped_percentages2 +0 -6
  118. data/test/multipart/filename_with_unescaped_percentages3 +0 -6
  119. data/test/multipart/filename_with_unescaped_quotes +0 -6
  120. data/test/multipart/ie +0 -6
  121. data/test/multipart/invalid_character +0 -6
  122. data/test/multipart/mixed_files +0 -21
  123. data/test/multipart/nested +0 -10
  124. data/test/multipart/none +0 -9
  125. data/test/multipart/quoted +0 -15
  126. data/test/multipart/rack-logo.png +0 -0
  127. data/test/multipart/semicolon +0 -6
  128. data/test/multipart/text +0 -15
  129. data/test/multipart/three_files_three_fields +0 -31
  130. data/test/multipart/unity3d_wwwform +0 -11
  131. data/test/multipart/webkit +0 -32
  132. data/test/rackup/config.ru +0 -31
  133. data/test/registering_handler/rack/handler/registering_myself.rb +0 -8
  134. data/test/spec_auth_basic.rb +0 -89
  135. data/test/spec_auth_digest.rb +0 -260
  136. data/test/spec_body_proxy.rb +0 -85
  137. data/test/spec_builder.rb +0 -233
  138. data/test/spec_cascade.rb +0 -63
  139. data/test/spec_cgi.rb +0 -84
  140. data/test/spec_chunked.rb +0 -103
  141. data/test/spec_common_logger.rb +0 -95
  142. data/test/spec_conditional_get.rb +0 -103
  143. data/test/spec_config.rb +0 -23
  144. data/test/spec_content_length.rb +0 -86
  145. data/test/spec_content_type.rb +0 -46
  146. data/test/spec_deflater.rb +0 -375
  147. data/test/spec_directory.rb +0 -148
  148. data/test/spec_etag.rb +0 -108
  149. data/test/spec_events.rb +0 -133
  150. data/test/spec_fastcgi.rb +0 -85
  151. data/test/spec_file.rb +0 -264
  152. data/test/spec_handler.rb +0 -57
  153. data/test/spec_head.rb +0 -46
  154. data/test/spec_lint.rb +0 -515
  155. data/test/spec_lobster.rb +0 -59
  156. data/test/spec_lock.rb +0 -194
  157. data/test/spec_logger.rb +0 -24
  158. data/test/spec_media_type.rb +0 -42
  159. data/test/spec_method_override.rb +0 -96
  160. data/test/spec_mime.rb +0 -51
  161. data/test/spec_mock.rb +0 -359
  162. data/test/spec_multipart.rb +0 -722
  163. data/test/spec_null_logger.rb +0 -21
  164. data/test/spec_recursive.rb +0 -75
  165. data/test/spec_request.rb +0 -1393
  166. data/test/spec_response.rb +0 -510
  167. data/test/spec_rewindable_input.rb +0 -128
  168. data/test/spec_runtime.rb +0 -50
  169. data/test/spec_sendfile.rb +0 -125
  170. data/test/spec_server.rb +0 -193
  171. data/test/spec_session_abstract_id.rb +0 -31
  172. data/test/spec_session_abstract_session_hash.rb +0 -45
  173. data/test/spec_session_cookie.rb +0 -442
  174. data/test/spec_session_memcache.rb +0 -320
  175. data/test/spec_session_pool.rb +0 -210
  176. data/test/spec_show_exceptions.rb +0 -80
  177. data/test/spec_show_status.rb +0 -104
  178. data/test/spec_static.rb +0 -184
  179. data/test/spec_tempfile_reaper.rb +0 -64
  180. data/test/spec_thin.rb +0 -96
  181. data/test/spec_urlmap.rb +0 -237
  182. data/test/spec_utils.rb +0 -742
  183. data/test/spec_version.rb +0 -11
  184. data/test/spec_webrick.rb +0 -209
  185. data/test/static/another/index.html +0 -1
  186. data/test/static/foo.html +0 -1
  187. data/test/static/index.html +0 -1
  188. data/test/testrequest.rb +0 -78
  189. data/test/unregistered_handler/rack/handler/unregistered.rb +0 -7
  190. data/test/unregistered_handler/rack/handler/unregistered_long_one.rb +0 -7
@@ -1,104 +0,0 @@
1
- require 'minitest/autorun'
2
- require 'rack/show_status'
3
- require 'rack/lint'
4
- require 'rack/mock'
5
- require 'rack/utils'
6
-
7
- describe Rack::ShowStatus do
8
- def show_status(app)
9
- Rack::Lint.new Rack::ShowStatus.new(app)
10
- end
11
-
12
- it "provide a default status message" do
13
- req = Rack::MockRequest.new(
14
- show_status(lambda{|env|
15
- [404, {"Content-Type" => "text/plain", "Content-Length" => "0"}, []]
16
- }))
17
-
18
- res = req.get("/", :lint => true)
19
- res.must_be :not_found?
20
- res.wont_be_empty
21
-
22
- res["Content-Type"].must_equal "text/html"
23
- assert_match(res, /404/)
24
- assert_match(res, /Not Found/)
25
- end
26
-
27
- it "let the app provide additional information" do
28
- req = Rack::MockRequest.new(
29
- show_status(
30
- lambda{|env|
31
- env["rack.showstatus.detail"] = "gone too meta."
32
- [404, {"Content-Type" => "text/plain", "Content-Length" => "0"}, []]
33
- }))
34
-
35
- res = req.get("/", :lint => true)
36
- res.must_be :not_found?
37
- res.wont_be_empty
38
-
39
- res["Content-Type"].must_equal "text/html"
40
- assert_match(res, /404/)
41
- assert_match(res, /Not Found/)
42
- assert_match(res, /too meta/)
43
- end
44
-
45
- it "escape error" do
46
- detail = "<script>alert('hi \"')</script>"
47
- req = Rack::MockRequest.new(
48
- show_status(
49
- lambda{|env|
50
- env["rack.showstatus.detail"] = detail
51
- [500, {"Content-Type" => "text/plain", "Content-Length" => "0"}, []]
52
- }))
53
-
54
- res = req.get("/", :lint => true)
55
- res.wont_be_empty
56
-
57
- res["Content-Type"].must_equal "text/html"
58
- assert_match(res, /500/)
59
- res.wont_include detail
60
- res.body.must_include Rack::Utils.escape_html(detail)
61
- end
62
-
63
- it "not replace existing messages" do
64
- req = Rack::MockRequest.new(
65
- show_status(
66
- lambda{|env|
67
- [404, {"Content-Type" => "text/plain", "Content-Length" => "4"}, ["foo!"]]
68
- }))
69
-
70
- res = req.get("/", :lint => true)
71
- res.must_be :not_found?
72
-
73
- res.body.must_equal "foo!"
74
- end
75
-
76
- it "pass on original headers" do
77
- headers = {"WWW-Authenticate" => "Basic blah"}
78
-
79
- req = Rack::MockRequest.new(
80
- show_status(lambda{|env| [401, headers, []] }))
81
- res = req.get("/", :lint => true)
82
-
83
- res["WWW-Authenticate"].must_equal "Basic blah"
84
- end
85
-
86
- it "replace existing messages if there is detail" do
87
- req = Rack::MockRequest.new(
88
- show_status(
89
- lambda{|env|
90
- env["rack.showstatus.detail"] = "gone too meta."
91
- [404, {"Content-Type" => "text/plain", "Content-Length" => "4"}, ["foo!"]]
92
- }))
93
-
94
- res = req.get("/", :lint => true)
95
- res.must_be :not_found?
96
- res.wont_be_empty
97
-
98
- res["Content-Type"].must_equal "text/html"
99
- res["Content-Length"].wont_equal "4"
100
- assert_match(res, /404/)
101
- assert_match(res, /too meta/)
102
- res.body.wont_match(/foo/)
103
- end
104
- end
data/test/spec_static.rb DELETED
@@ -1,184 +0,0 @@
1
- require 'minitest/autorun'
2
- require 'rack/static'
3
- require 'rack/lint'
4
- require 'rack/mock'
5
- require 'zlib'
6
- require 'stringio'
7
-
8
- class DummyApp
9
- def call(env)
10
- [200, {"Content-Type" => "text/plain"}, ["Hello World"]]
11
- end
12
- end
13
-
14
- describe Rack::Static do
15
- def static(app, *args)
16
- Rack::Lint.new Rack::Static.new(app, *args)
17
- end
18
-
19
- root = File.expand_path(File.dirname(__FILE__))
20
-
21
- OPTIONS = {:urls => ["/cgi"], :root => root}
22
- STATIC_OPTIONS = {:urls => [""], :root => "#{root}/static", :index => 'index.html'}
23
- HASH_OPTIONS = {:urls => {"/cgi/sekret" => 'cgi/test'}, :root => root}
24
- HASH_ROOT_OPTIONS = {:urls => {"/" => "static/foo.html"}, :root => root}
25
- GZIP_OPTIONS = {:urls => ["/cgi"], :root => root, :gzip=>true}
26
-
27
- before do
28
- @request = Rack::MockRequest.new(static(DummyApp.new, OPTIONS))
29
- @static_request = Rack::MockRequest.new(static(DummyApp.new, STATIC_OPTIONS))
30
- @hash_request = Rack::MockRequest.new(static(DummyApp.new, HASH_OPTIONS))
31
- @hash_root_request = Rack::MockRequest.new(static(DummyApp.new, HASH_ROOT_OPTIONS))
32
- @gzip_request = Rack::MockRequest.new(static(DummyApp.new, GZIP_OPTIONS))
33
- @header_request = Rack::MockRequest.new(static(DummyApp.new, HEADER_OPTIONS))
34
- end
35
-
36
- it "serves files" do
37
- res = @request.get("/cgi/test")
38
- res.must_be :ok?
39
- res.body.must_match(/ruby/)
40
- end
41
-
42
- it "404s if url root is known but it can't find the file" do
43
- res = @request.get("/cgi/foo")
44
- res.must_be :not_found?
45
- end
46
-
47
- it "calls down the chain if url root is not known" do
48
- res = @request.get("/something/else")
49
- res.must_be :ok?
50
- res.body.must_equal "Hello World"
51
- end
52
-
53
- it "calls index file when requesting root in the given folder" do
54
- res = @static_request.get("/")
55
- res.must_be :ok?
56
- res.body.must_match(/index!/)
57
-
58
- res = @static_request.get("/other/")
59
- res.must_be :not_found?
60
-
61
- res = @static_request.get("/another/")
62
- res.must_be :ok?
63
- res.body.must_match(/another index!/)
64
- end
65
-
66
- it "doesn't call index file if :index option was omitted" do
67
- res = @request.get("/")
68
- res.body.must_equal "Hello World"
69
- end
70
-
71
- it "serves hidden files" do
72
- res = @hash_request.get("/cgi/sekret")
73
- res.must_be :ok?
74
- res.body.must_match(/ruby/)
75
- end
76
-
77
- it "calls down the chain if the URI is not specified" do
78
- res = @hash_request.get("/something/else")
79
- res.must_be :ok?
80
- res.body.must_equal "Hello World"
81
- end
82
-
83
- it "allows the root URI to be configured via hash options" do
84
- res = @hash_root_request.get("/")
85
- res.must_be :ok?
86
- res.body.must_match(/foo.html!/)
87
- end
88
-
89
- it "serves gzipped files if client accepts gzip encoding and gzip files are present" do
90
- res = @gzip_request.get("/cgi/test", 'HTTP_ACCEPT_ENCODING'=>'deflate, gzip')
91
- res.must_be :ok?
92
- res.headers['Content-Encoding'].must_equal 'gzip'
93
- res.headers['Content-Type'].must_equal 'text/plain'
94
- Zlib::GzipReader.wrap(StringIO.new(res.body), &:read).must_match(/ruby/)
95
- end
96
-
97
- it "serves regular files if client accepts gzip encoding and gzip files are not present" do
98
- res = @gzip_request.get("/cgi/rackup_stub.rb", 'HTTP_ACCEPT_ENCODING'=>'deflate, gzip')
99
- res.must_be :ok?
100
- res.headers['Content-Encoding'].must_be_nil
101
- res.headers['Content-Type'].must_equal 'text/x-script.ruby'
102
- res.body.must_match(/ruby/)
103
- end
104
-
105
- it "serves regular files if client does not accept gzip encoding" do
106
- res = @gzip_request.get("/cgi/test")
107
- res.must_be :ok?
108
- res.headers['Content-Encoding'].must_be_nil
109
- res.headers['Content-Type'].must_equal 'text/plain'
110
- res.body.must_match(/ruby/)
111
- end
112
-
113
- it "supports serving fixed cache-control (legacy option)" do
114
- opts = OPTIONS.merge(:cache_control => 'public')
115
- request = Rack::MockRequest.new(static(DummyApp.new, opts))
116
- res = request.get("/cgi/test")
117
- res.must_be :ok?
118
- res.headers['Cache-Control'].must_equal 'public'
119
- end
120
-
121
- HEADER_OPTIONS = {:urls => ["/cgi"], :root => root, :header_rules => [
122
- [:all, {'Cache-Control' => 'public, max-age=100'}],
123
- [:fonts, {'Cache-Control' => 'public, max-age=200'}],
124
- [%w(png jpg), {'Cache-Control' => 'public, max-age=300'}],
125
- ['/cgi/assets/folder/', {'Cache-Control' => 'public, max-age=400'}],
126
- ['cgi/assets/javascripts', {'Cache-Control' => 'public, max-age=500'}],
127
- [/\.(css|erb)\z/, {'Cache-Control' => 'public, max-age=600'}]
128
- ]}
129
-
130
- it "supports header rule :all" do
131
- # Headers for all files via :all shortcut
132
- res = @header_request.get('/cgi/assets/index.html')
133
- res.must_be :ok?
134
- res.headers['Cache-Control'].must_equal 'public, max-age=100'
135
- end
136
-
137
- it "supports header rule :fonts" do
138
- # Headers for web fonts via :fonts shortcut
139
- res = @header_request.get('/cgi/assets/fonts/font.eot')
140
- res.must_be :ok?
141
- res.headers['Cache-Control'].must_equal 'public, max-age=200'
142
- end
143
-
144
- it "supports file extension header rules provided as an Array" do
145
- # Headers for file extensions via array
146
- res = @header_request.get('/cgi/assets/images/image.png')
147
- res.must_be :ok?
148
- res.headers['Cache-Control'].must_equal 'public, max-age=300'
149
- end
150
-
151
- it "supports folder rules provided as a String" do
152
- # Headers for files in folder via string
153
- res = @header_request.get('/cgi/assets/folder/test.js')
154
- res.must_be :ok?
155
- res.headers['Cache-Control'].must_equal 'public, max-age=400'
156
- end
157
-
158
- it "supports folder header rules provided as a String not starting with a slash" do
159
- res = @header_request.get('/cgi/assets/javascripts/app.js')
160
- res.must_be :ok?
161
- res.headers['Cache-Control'].must_equal 'public, max-age=500'
162
- end
163
-
164
- it "supports flexible header rules provided as Regexp" do
165
- # Flexible Headers via Regexp
166
- res = @header_request.get('/cgi/assets/stylesheets/app.css')
167
- res.must_be :ok?
168
- res.headers['Cache-Control'].must_equal 'public, max-age=600'
169
- end
170
-
171
- it "prioritizes header rules over fixed cache-control setting (legacy option)" do
172
- opts = OPTIONS.merge(
173
- :cache_control => 'public, max-age=24',
174
- :header_rules => [
175
- [:all, {'Cache-Control' => 'public, max-age=42'}]
176
- ])
177
-
178
- request = Rack::MockRequest.new(static(DummyApp.new, opts))
179
- res = request.get("/cgi/test")
180
- res.must_be :ok?
181
- res.headers['Cache-Control'].must_equal 'public, max-age=42'
182
- end
183
-
184
- end
@@ -1,64 +0,0 @@
1
- require 'minitest/autorun'
2
- require 'rack/tempfile_reaper'
3
- require 'rack/lint'
4
- require 'rack/mock'
5
-
6
- describe Rack::TempfileReaper do
7
- class MockTempfile
8
- attr_reader :closed
9
-
10
- def initialize
11
- @closed = false
12
- end
13
-
14
- def close!
15
- @closed = true
16
- end
17
- end
18
-
19
- before do
20
- @env = Rack::MockRequest.env_for
21
- end
22
-
23
- def call(app)
24
- Rack::Lint.new(Rack::TempfileReaper.new(app)).call(@env)
25
- end
26
-
27
- it 'do nothing (i.e. not bomb out) without env[rack.tempfiles]' do
28
- app = lambda { |_| [200, {}, ['Hello, World!']] }
29
- response = call(app)
30
- response[2].close
31
- response[0].must_equal 200
32
- end
33
-
34
- it 'close env[rack.tempfiles] when body is closed' do
35
- tempfile1, tempfile2 = MockTempfile.new, MockTempfile.new
36
- @env['rack.tempfiles'] = [ tempfile1, tempfile2 ]
37
- app = lambda { |_| [200, {}, ['Hello, World!']] }
38
- call(app)[2].close
39
- tempfile1.closed.must_equal true
40
- tempfile2.closed.must_equal true
41
- end
42
-
43
- it 'initialize env[rack.tempfiles] when not already present' do
44
- tempfile = MockTempfile.new
45
- app = lambda do |env|
46
- env['rack.tempfiles'] << tempfile
47
- [200, {}, ['Hello, World!']]
48
- end
49
- call(app)[2].close
50
- tempfile.closed.must_equal true
51
- end
52
-
53
- it 'append env[rack.tempfiles] when already present' do
54
- tempfile1, tempfile2 = MockTempfile.new, MockTempfile.new
55
- @env['rack.tempfiles'] = [ tempfile1 ]
56
- app = lambda do |env|
57
- env['rack.tempfiles'] << tempfile2
58
- [200, {}, ['Hello, World!']]
59
- end
60
- call(app)[2].close
61
- tempfile1.closed.must_equal true
62
- tempfile2.closed.must_equal true
63
- end
64
- end
data/test/spec_thin.rb DELETED
@@ -1,96 +0,0 @@
1
- require 'minitest/autorun'
2
- begin
3
- require 'rack/handler/thin'
4
- require File.expand_path('../testrequest', __FILE__)
5
- require 'timeout'
6
-
7
- describe Rack::Handler::Thin do
8
- include TestRequest::Helpers
9
-
10
- before do
11
- @app = Rack::Lint.new(TestRequest.new)
12
- @server = nil
13
- Thin::Logging.silent = true
14
-
15
- @thread = Thread.new do
16
- Rack::Handler::Thin.run(@app, :Host => @host='127.0.0.1', :Port => @port=9204, :tag => "tag") do |server|
17
- @server = server
18
- end
19
- end
20
-
21
- Thread.pass until @server && @server.running?
22
- end
23
-
24
- after do
25
- @server.stop!
26
- @thread.join
27
- end
28
-
29
-
30
- it "respond" do
31
- GET("/")
32
- response.wont_be :nil?
33
- end
34
-
35
- it "be a Thin" do
36
- GET("/")
37
- status.must_equal 200
38
- response["SERVER_SOFTWARE"].must_match(/thin/)
39
- response["HTTP_VERSION"].must_equal "HTTP/1.1"
40
- response["SERVER_PROTOCOL"].must_equal "HTTP/1.1"
41
- response["SERVER_PORT"].must_equal "9204"
42
- response["SERVER_NAME"].must_equal "127.0.0.1"
43
- end
44
-
45
- it "have rack headers" do
46
- GET("/")
47
- response["rack.version"].must_equal [1,0]
48
- response["rack.multithread"].must_equal false
49
- response["rack.multiprocess"].must_equal false
50
- response["rack.run_once"].must_equal false
51
- end
52
-
53
- it "have CGI headers on GET" do
54
- GET("/")
55
- response["REQUEST_METHOD"].must_equal "GET"
56
- response["REQUEST_PATH"].must_equal "/"
57
- response["PATH_INFO"].must_equal "/"
58
- response["QUERY_STRING"].must_equal ""
59
- response["test.postdata"].must_equal ""
60
-
61
- GET("/test/foo?quux=1")
62
- response["REQUEST_METHOD"].must_equal "GET"
63
- response["REQUEST_PATH"].must_equal "/test/foo"
64
- response["PATH_INFO"].must_equal "/test/foo"
65
- response["QUERY_STRING"].must_equal "quux=1"
66
- end
67
-
68
- it "have CGI headers on POST" do
69
- POST("/", {"rack-form-data" => "23"}, {'X-test-header' => '42'})
70
- status.must_equal 200
71
- response["REQUEST_METHOD"].must_equal "POST"
72
- response["REQUEST_PATH"].must_equal "/"
73
- response["QUERY_STRING"].must_equal ""
74
- response["HTTP_X_TEST_HEADER"].must_equal "42"
75
- response["test.postdata"].must_equal "rack-form-data=23"
76
- end
77
-
78
- it "support HTTP auth" do
79
- GET("/test", {:user => "ruth", :passwd => "secret"})
80
- response["HTTP_AUTHORIZATION"].must_equal "Basic cnV0aDpzZWNyZXQ="
81
- end
82
-
83
- it "set status" do
84
- GET("/test?secret")
85
- status.must_equal 403
86
- response["rack.url_scheme"].must_equal "http"
87
- end
88
-
89
- it "set tag for server" do
90
- @server.tag.must_equal 'tag'
91
- end
92
- end
93
-
94
- rescue LoadError
95
- $stderr.puts "Skipping Rack::Handler::Thin tests (Thin is required). `gem install thin` and try again."
96
- end
data/test/spec_urlmap.rb DELETED
@@ -1,237 +0,0 @@
1
- require 'minitest/autorun'
2
- require 'rack/urlmap'
3
- require 'rack/mock'
4
-
5
- describe Rack::URLMap do
6
- it "dispatches paths correctly" do
7
- app = lambda { |env|
8
- [200, {
9
- 'X-ScriptName' => env['SCRIPT_NAME'],
10
- 'X-PathInfo' => env['PATH_INFO'],
11
- 'Content-Type' => 'text/plain'
12
- }, [""]]
13
- }
14
- map = Rack::Lint.new(Rack::URLMap.new({
15
- 'http://foo.org/bar' => app,
16
- '/foo' => app,
17
- '/foo/bar' => app
18
- }))
19
-
20
- res = Rack::MockRequest.new(map).get("/")
21
- res.must_be :not_found?
22
-
23
- res = Rack::MockRequest.new(map).get("/qux")
24
- res.must_be :not_found?
25
-
26
- res = Rack::MockRequest.new(map).get("/foo")
27
- res.must_be :ok?
28
- res["X-ScriptName"].must_equal "/foo"
29
- res["X-PathInfo"].must_equal ""
30
-
31
- res = Rack::MockRequest.new(map).get("/foo/")
32
- res.must_be :ok?
33
- res["X-ScriptName"].must_equal "/foo"
34
- res["X-PathInfo"].must_equal "/"
35
-
36
- res = Rack::MockRequest.new(map).get("/foo/bar")
37
- res.must_be :ok?
38
- res["X-ScriptName"].must_equal "/foo/bar"
39
- res["X-PathInfo"].must_equal ""
40
-
41
- res = Rack::MockRequest.new(map).get("/foo/bar/")
42
- res.must_be :ok?
43
- res["X-ScriptName"].must_equal "/foo/bar"
44
- res["X-PathInfo"].must_equal "/"
45
-
46
- res = Rack::MockRequest.new(map).get("/foo///bar//quux")
47
- res.status.must_equal 200
48
- res.must_be :ok?
49
- res["X-ScriptName"].must_equal "/foo/bar"
50
- res["X-PathInfo"].must_equal "//quux"
51
-
52
- res = Rack::MockRequest.new(map).get("/foo/quux", "SCRIPT_NAME" => "/bleh")
53
- res.must_be :ok?
54
- res["X-ScriptName"].must_equal "/bleh/foo"
55
- res["X-PathInfo"].must_equal "/quux"
56
-
57
- res = Rack::MockRequest.new(map).get("/bar", 'HTTP_HOST' => 'foo.org')
58
- res.must_be :ok?
59
- res["X-ScriptName"].must_equal "/bar"
60
- res["X-PathInfo"].must_be :empty?
61
-
62
- res = Rack::MockRequest.new(map).get("/bar/", 'HTTP_HOST' => 'foo.org')
63
- res.must_be :ok?
64
- res["X-ScriptName"].must_equal "/bar"
65
- res["X-PathInfo"].must_equal '/'
66
- end
67
-
68
-
69
- it "dispatches hosts correctly" do
70
- map = Rack::Lint.new(Rack::URLMap.new("http://foo.org/" => lambda { |env|
71
- [200,
72
- { "Content-Type" => "text/plain",
73
- "X-Position" => "foo.org",
74
- "X-Host" => env["HTTP_HOST"] || env["SERVER_NAME"],
75
- }, [""]]},
76
- "http://subdomain.foo.org/" => lambda { |env|
77
- [200,
78
- { "Content-Type" => "text/plain",
79
- "X-Position" => "subdomain.foo.org",
80
- "X-Host" => env["HTTP_HOST"] || env["SERVER_NAME"],
81
- }, [""]]},
82
- "http://bar.org/" => lambda { |env|
83
- [200,
84
- { "Content-Type" => "text/plain",
85
- "X-Position" => "bar.org",
86
- "X-Host" => env["HTTP_HOST"] || env["SERVER_NAME"],
87
- }, [""]]},
88
- "/" => lambda { |env|
89
- [200,
90
- { "Content-Type" => "text/plain",
91
- "X-Position" => "default.org",
92
- "X-Host" => env["HTTP_HOST"] || env["SERVER_NAME"],
93
- }, [""]]}
94
- ))
95
-
96
- res = Rack::MockRequest.new(map).get("/")
97
- res.must_be :ok?
98
- res["X-Position"].must_equal "default.org"
99
-
100
- res = Rack::MockRequest.new(map).get("/", "HTTP_HOST" => "bar.org")
101
- res.must_be :ok?
102
- res["X-Position"].must_equal "bar.org"
103
-
104
- res = Rack::MockRequest.new(map).get("/", "HTTP_HOST" => "foo.org")
105
- res.must_be :ok?
106
- res["X-Position"].must_equal "foo.org"
107
-
108
- res = Rack::MockRequest.new(map).get("/", "HTTP_HOST" => "subdomain.foo.org", "SERVER_NAME" => "foo.org")
109
- res.must_be :ok?
110
- res["X-Position"].must_equal "subdomain.foo.org"
111
-
112
- res = Rack::MockRequest.new(map).get("http://foo.org/")
113
- res.must_be :ok?
114
- res["X-Position"].must_equal "foo.org"
115
-
116
- res = Rack::MockRequest.new(map).get("/", "HTTP_HOST" => "example.org")
117
- res.must_be :ok?
118
- res["X-Position"].must_equal "default.org"
119
-
120
- res = Rack::MockRequest.new(map).get("/",
121
- "HTTP_HOST" => "example.org:9292",
122
- "SERVER_PORT" => "9292")
123
- res.must_be :ok?
124
- res["X-Position"].must_equal "default.org"
125
- end
126
-
127
- it "be nestable" do
128
- map = Rack::Lint.new(Rack::URLMap.new("/foo" =>
129
- Rack::URLMap.new("/bar" =>
130
- Rack::URLMap.new("/quux" => lambda { |env|
131
- [200,
132
- { "Content-Type" => "text/plain",
133
- "X-Position" => "/foo/bar/quux",
134
- "X-PathInfo" => env["PATH_INFO"],
135
- "X-ScriptName" => env["SCRIPT_NAME"],
136
- }, [""]]}
137
- ))))
138
-
139
- res = Rack::MockRequest.new(map).get("/foo/bar")
140
- res.must_be :not_found?
141
-
142
- res = Rack::MockRequest.new(map).get("/foo/bar/quux")
143
- res.must_be :ok?
144
- res["X-Position"].must_equal "/foo/bar/quux"
145
- res["X-PathInfo"].must_equal ""
146
- res["X-ScriptName"].must_equal "/foo/bar/quux"
147
- end
148
-
149
- it "route root apps correctly" do
150
- map = Rack::Lint.new(Rack::URLMap.new("/" => lambda { |env|
151
- [200,
152
- { "Content-Type" => "text/plain",
153
- "X-Position" => "root",
154
- "X-PathInfo" => env["PATH_INFO"],
155
- "X-ScriptName" => env["SCRIPT_NAME"]
156
- }, [""]]},
157
- "/foo" => lambda { |env|
158
- [200,
159
- { "Content-Type" => "text/plain",
160
- "X-Position" => "foo",
161
- "X-PathInfo" => env["PATH_INFO"],
162
- "X-ScriptName" => env["SCRIPT_NAME"]
163
- }, [""]]}
164
- ))
165
-
166
- res = Rack::MockRequest.new(map).get("/foo/bar")
167
- res.must_be :ok?
168
- res["X-Position"].must_equal "foo"
169
- res["X-PathInfo"].must_equal "/bar"
170
- res["X-ScriptName"].must_equal "/foo"
171
-
172
- res = Rack::MockRequest.new(map).get("/foo")
173
- res.must_be :ok?
174
- res["X-Position"].must_equal "foo"
175
- res["X-PathInfo"].must_equal ""
176
- res["X-ScriptName"].must_equal "/foo"
177
-
178
- res = Rack::MockRequest.new(map).get("/bar")
179
- res.must_be :ok?
180
- res["X-Position"].must_equal "root"
181
- res["X-PathInfo"].must_equal "/bar"
182
- res["X-ScriptName"].must_equal ""
183
-
184
- res = Rack::MockRequest.new(map).get("")
185
- res.must_be :ok?
186
- res["X-Position"].must_equal "root"
187
- res["X-PathInfo"].must_equal "/"
188
- res["X-ScriptName"].must_equal ""
189
- end
190
-
191
- it "not squeeze slashes" do
192
- map = Rack::Lint.new(Rack::URLMap.new("/" => lambda { |env|
193
- [200,
194
- { "Content-Type" => "text/plain",
195
- "X-Position" => "root",
196
- "X-PathInfo" => env["PATH_INFO"],
197
- "X-ScriptName" => env["SCRIPT_NAME"]
198
- }, [""]]},
199
- "/foo" => lambda { |env|
200
- [200,
201
- { "Content-Type" => "text/plain",
202
- "X-Position" => "foo",
203
- "X-PathInfo" => env["PATH_INFO"],
204
- "X-ScriptName" => env["SCRIPT_NAME"]
205
- }, [""]]}
206
- ))
207
-
208
- res = Rack::MockRequest.new(map).get("/http://example.org/bar")
209
- res.must_be :ok?
210
- res["X-Position"].must_equal "root"
211
- res["X-PathInfo"].must_equal "/http://example.org/bar"
212
- res["X-ScriptName"].must_equal ""
213
- end
214
-
215
- it "not be case sensitive with hosts" do
216
- map = Rack::Lint.new(Rack::URLMap.new("http://example.org/" => lambda { |env|
217
- [200,
218
- { "Content-Type" => "text/plain",
219
- "X-Position" => "root",
220
- "X-PathInfo" => env["PATH_INFO"],
221
- "X-ScriptName" => env["SCRIPT_NAME"]
222
- }, [""]]}
223
- ))
224
-
225
- res = Rack::MockRequest.new(map).get("http://example.org/")
226
- res.must_be :ok?
227
- res["X-Position"].must_equal "root"
228
- res["X-PathInfo"].must_equal "/"
229
- res["X-ScriptName"].must_equal ""
230
-
231
- res = Rack::MockRequest.new(map).get("http://EXAMPLE.ORG/")
232
- res.must_be :ok?
233
- res["X-Position"].must_equal "root"
234
- res["X-PathInfo"].must_equal "/"
235
- res["X-ScriptName"].must_equal ""
236
- end
237
- end