rack 1.4.7 → 2.1.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 (183) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +77 -0
  3. data/{COPYING → MIT-LICENSE} +4 -2
  4. data/README.rdoc +122 -456
  5. data/Rakefile +32 -31
  6. data/SPEC +119 -29
  7. data/bin/rackup +1 -0
  8. data/contrib/rack_logo.svg +164 -111
  9. data/example/lobster.ru +2 -0
  10. data/example/protectedlobster.rb +4 -2
  11. data/example/protectedlobster.ru +3 -1
  12. data/lib/rack/auth/abstract/handler.rb +7 -5
  13. data/lib/rack/auth/abstract/request.rb +8 -6
  14. data/lib/rack/auth/basic.rb +5 -2
  15. data/lib/rack/auth/digest/md5.rb +10 -8
  16. data/lib/rack/auth/digest/nonce.rb +6 -3
  17. data/lib/rack/auth/digest/params.rb +5 -4
  18. data/lib/rack/auth/digest/request.rb +4 -2
  19. data/lib/rack/body_proxy.rb +11 -9
  20. data/lib/rack/builder.rb +63 -20
  21. data/lib/rack/cascade.rb +10 -9
  22. data/lib/rack/chunked.rb +45 -11
  23. data/lib/rack/{commonlogger.rb → common_logger.rb} +24 -15
  24. data/lib/rack/{conditionalget.rb → conditional_get.rb} +20 -6
  25. data/lib/rack/config.rb +7 -0
  26. data/lib/rack/content_length.rb +12 -6
  27. data/lib/rack/content_type.rb +4 -2
  28. data/lib/rack/core_ext/regexp.rb +14 -0
  29. data/lib/rack/deflater.rb +73 -42
  30. data/lib/rack/directory.rb +77 -56
  31. data/lib/rack/etag.rb +25 -13
  32. data/lib/rack/events.rb +156 -0
  33. data/lib/rack/file.rb +4 -143
  34. data/lib/rack/files.rb +178 -0
  35. data/lib/rack/handler/cgi.rb +18 -17
  36. data/lib/rack/handler/fastcgi.rb +21 -17
  37. data/lib/rack/handler/lsws.rb +14 -12
  38. data/lib/rack/handler/scgi.rb +27 -21
  39. data/lib/rack/handler/thin.rb +19 -5
  40. data/lib/rack/handler/webrick.rb +66 -24
  41. data/lib/rack/handler.rb +29 -19
  42. data/lib/rack/head.rb +21 -14
  43. data/lib/rack/lint.rb +259 -65
  44. data/lib/rack/lobster.rb +17 -10
  45. data/lib/rack/lock.rb +19 -10
  46. data/lib/rack/logger.rb +4 -2
  47. data/lib/rack/media_type.rb +43 -0
  48. data/lib/rack/method_override.rb +52 -0
  49. data/lib/rack/mime.rb +43 -6
  50. data/lib/rack/mock.rb +109 -44
  51. data/lib/rack/multipart/generator.rb +11 -12
  52. data/lib/rack/multipart/parser.rb +302 -115
  53. data/lib/rack/multipart/uploaded_file.rb +4 -3
  54. data/lib/rack/multipart.rb +40 -9
  55. data/lib/rack/null_logger.rb +39 -0
  56. data/lib/rack/query_parser.rb +218 -0
  57. data/lib/rack/recursive.rb +14 -11
  58. data/lib/rack/reloader.rb +12 -5
  59. data/lib/rack/request.rb +484 -270
  60. data/lib/rack/response.rb +196 -77
  61. data/lib/rack/rewindable_input.rb +5 -14
  62. data/lib/rack/runtime.rb +13 -6
  63. data/lib/rack/sendfile.rb +44 -20
  64. data/lib/rack/server.rb +175 -61
  65. data/lib/rack/session/abstract/id.rb +276 -133
  66. data/lib/rack/session/cookie.rb +75 -40
  67. data/lib/rack/session/memcache.rb +4 -87
  68. data/lib/rack/session/pool.rb +24 -18
  69. data/lib/rack/show_exceptions.rb +392 -0
  70. data/lib/rack/{showstatus.rb → show_status.rb} +11 -9
  71. data/lib/rack/static.rb +65 -38
  72. data/lib/rack/tempfile_reaper.rb +24 -0
  73. data/lib/rack/urlmap.rb +40 -15
  74. data/lib/rack/utils.rb +316 -285
  75. data/lib/rack.rb +78 -23
  76. data/rack.gemspec +26 -19
  77. metadata +44 -209
  78. data/KNOWN-ISSUES +0 -30
  79. data/lib/rack/backports/uri/common_18.rb +0 -56
  80. data/lib/rack/backports/uri/common_192.rb +0 -52
  81. data/lib/rack/backports/uri/common_193.rb +0 -29
  82. data/lib/rack/handler/evented_mongrel.rb +0 -8
  83. data/lib/rack/handler/mongrel.rb +0 -100
  84. data/lib/rack/handler/swiftiplied_mongrel.rb +0 -8
  85. data/lib/rack/methodoverride.rb +0 -33
  86. data/lib/rack/nulllogger.rb +0 -18
  87. data/lib/rack/showexceptions.rb +0 -378
  88. data/test/builder/anything.rb +0 -5
  89. data/test/builder/comment.ru +0 -4
  90. data/test/builder/end.ru +0 -5
  91. data/test/builder/line.ru +0 -1
  92. data/test/builder/options.ru +0 -2
  93. data/test/cgi/assets/folder/test.js +0 -1
  94. data/test/cgi/assets/fonts/font.eot +0 -1
  95. data/test/cgi/assets/images/image.png +0 -1
  96. data/test/cgi/assets/index.html +0 -1
  97. data/test/cgi/assets/javascripts/app.js +0 -1
  98. data/test/cgi/assets/stylesheets/app.css +0 -1
  99. data/test/cgi/lighttpd.conf +0 -26
  100. data/test/cgi/lighttpd.errors +0 -1
  101. data/test/cgi/rackup_stub.rb +0 -6
  102. data/test/cgi/sample_rackup.ru +0 -5
  103. data/test/cgi/test +0 -9
  104. data/test/cgi/test+directory/test+file +0 -1
  105. data/test/cgi/test.fcgi +0 -8
  106. data/test/cgi/test.ru +0 -5
  107. data/test/gemloader.rb +0 -10
  108. data/test/multipart/bad_robots +0 -259
  109. data/test/multipart/binary +0 -0
  110. data/test/multipart/content_type_and_no_filename +0 -6
  111. data/test/multipart/empty +0 -10
  112. data/test/multipart/fail_16384_nofile +0 -814
  113. data/test/multipart/file1.txt +0 -1
  114. data/test/multipart/filename_and_modification_param +0 -7
  115. data/test/multipart/filename_with_escaped_quotes +0 -6
  116. data/test/multipart/filename_with_escaped_quotes_and_modification_param +0 -7
  117. data/test/multipart/filename_with_percent_escaped_quotes +0 -6
  118. data/test/multipart/filename_with_unescaped_percentages +0 -6
  119. data/test/multipart/filename_with_unescaped_percentages2 +0 -6
  120. data/test/multipart/filename_with_unescaped_percentages3 +0 -6
  121. data/test/multipart/filename_with_unescaped_quotes +0 -6
  122. data/test/multipart/ie +0 -6
  123. data/test/multipart/mixed_files +0 -21
  124. data/test/multipart/nested +0 -10
  125. data/test/multipart/none +0 -9
  126. data/test/multipart/semicolon +0 -6
  127. data/test/multipart/text +0 -15
  128. data/test/multipart/three_files_three_fields +0 -31
  129. data/test/multipart/webkit +0 -32
  130. data/test/rackup/config.ru +0 -31
  131. data/test/registering_handler/rack/handler/registering_myself.rb +0 -8
  132. data/test/spec_auth.rb +0 -57
  133. data/test/spec_auth_basic.rb +0 -81
  134. data/test/spec_auth_digest.rb +0 -259
  135. data/test/spec_body_proxy.rb +0 -69
  136. data/test/spec_builder.rb +0 -207
  137. data/test/spec_cascade.rb +0 -61
  138. data/test/spec_cgi.rb +0 -102
  139. data/test/spec_chunked.rb +0 -87
  140. data/test/spec_commonlogger.rb +0 -57
  141. data/test/spec_conditionalget.rb +0 -102
  142. data/test/spec_config.rb +0 -22
  143. data/test/spec_content_length.rb +0 -86
  144. data/test/spec_content_type.rb +0 -45
  145. data/test/spec_deflater.rb +0 -187
  146. data/test/spec_directory.rb +0 -88
  147. data/test/spec_etag.rb +0 -98
  148. data/test/spec_fastcgi.rb +0 -107
  149. data/test/spec_file.rb +0 -200
  150. data/test/spec_handler.rb +0 -59
  151. data/test/spec_head.rb +0 -48
  152. data/test/spec_lint.rb +0 -515
  153. data/test/spec_lobster.rb +0 -58
  154. data/test/spec_lock.rb +0 -167
  155. data/test/spec_logger.rb +0 -23
  156. data/test/spec_methodoverride.rb +0 -72
  157. data/test/spec_mock.rb +0 -269
  158. data/test/spec_mongrel.rb +0 -182
  159. data/test/spec_multipart.rb +0 -479
  160. data/test/spec_nulllogger.rb +0 -23
  161. data/test/spec_recursive.rb +0 -72
  162. data/test/spec_request.rb +0 -955
  163. data/test/spec_response.rb +0 -313
  164. data/test/spec_rewindable_input.rb +0 -118
  165. data/test/spec_runtime.rb +0 -49
  166. data/test/spec_sendfile.rb +0 -90
  167. data/test/spec_server.rb +0 -121
  168. data/test/spec_session_abstract_id.rb +0 -43
  169. data/test/spec_session_cookie.rb +0 -361
  170. data/test/spec_session_memcache.rb +0 -321
  171. data/test/spec_session_pool.rb +0 -209
  172. data/test/spec_showexceptions.rb +0 -92
  173. data/test/spec_showstatus.rb +0 -84
  174. data/test/spec_static.rb +0 -145
  175. data/test/spec_thin.rb +0 -86
  176. data/test/spec_urlmap.rb +0 -213
  177. data/test/spec_utils.rb +0 -554
  178. data/test/spec_webrick.rb +0 -143
  179. data/test/static/another/index.html +0 -1
  180. data/test/static/index.html +0 -1
  181. data/test/testrequest.rb +0 -78
  182. data/test/unregistered_handler/rack/handler/unregistered.rb +0 -7
  183. data/test/unregistered_handler/rack/handler/unregistered_long_one.rb +0 -7
data/test/spec_config.rb DELETED
@@ -1,22 +0,0 @@
1
- require 'rack/builder'
2
- require 'rack/config'
3
- require 'rack/content_length'
4
- require 'rack/lint'
5
- require 'rack/mock'
6
-
7
- describe Rack::Config do
8
- should "accept a block that modifies the environment" do
9
- app = Rack::Builder.new do
10
- use Rack::Lint
11
- use Rack::Config do |env|
12
- env['greeting'] = 'hello'
13
- end
14
- run lambda { |env|
15
- [200, {'Content-Type' => 'text/plain'}, [env['greeting'] || '']]
16
- }
17
- end
18
-
19
- response = Rack::MockRequest.new(app).get('/')
20
- response.body.should.equal('hello')
21
- end
22
- end
@@ -1,86 +0,0 @@
1
- require 'enumerator'
2
- require 'rack/content_length'
3
- require 'rack/lint'
4
- require 'rack/mock'
5
-
6
- describe Rack::ContentLength do
7
- ::Enumerator = ::Enumerable::Enumerator unless Object.const_defined?(:Enumerator)
8
-
9
- def content_length(app)
10
- Rack::Lint.new Rack::ContentLength.new(app)
11
- end
12
-
13
- def request
14
- Rack::MockRequest.env_for
15
- end
16
-
17
- should "set Content-Length on Array bodies if none is set" do
18
- app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, ["Hello, World!"]] }
19
- response = content_length(app).call(request)
20
- response[1]['Content-Length'].should.equal '13'
21
- end
22
-
23
- should "not set Content-Length on variable length bodies" do
24
- body = lambda { "Hello World!" }
25
- def body.each ; yield call ; end
26
-
27
- app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, body] }
28
- response = content_length(app).call(request)
29
- response[1]['Content-Length'].should.be.nil
30
- end
31
-
32
- should "not change Content-Length if it is already set" do
33
- app = lambda { |env| [200, {'Content-Type' => 'text/plain', 'Content-Length' => '1'}, "Hello, World!"] }
34
- response = content_length(app).call(request)
35
- response[1]['Content-Length'].should.equal '1'
36
- end
37
-
38
- should "not set Content-Length on 304 responses" do
39
- app = lambda { |env| [304, {}, []] }
40
- response = content_length(app).call(request)
41
- response[1]['Content-Length'].should.equal nil
42
- end
43
-
44
- should "not set Content-Length when Transfer-Encoding is chunked" do
45
- app = lambda { |env| [200, {'Content-Type' => 'text/plain', 'Transfer-Encoding' => 'chunked'}, []] }
46
- response = content_length(app).call(request)
47
- response[1]['Content-Length'].should.equal nil
48
- end
49
-
50
- # Using "Connection: close" for this is fairly contended. It might be useful
51
- # to have some other way to signal this.
52
- #
53
- # should "not force a Content-Length when Connection:close" do
54
- # app = lambda { |env| [200, {'Connection' => 'close'}, []] }
55
- # response = content_length(app).call({})
56
- # response[1]['Content-Length'].should.equal nil
57
- # end
58
-
59
- should "close bodies that need to be closed" do
60
- body = Struct.new(:body) do
61
- attr_reader :closed
62
- def each; body.join; end
63
- def close; @closed = true; end
64
- def to_ary; end
65
- end.new(%w[one two three])
66
-
67
- app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, body] }
68
- content_length(app).call(request)
69
- body.closed.should.equal true
70
- end
71
-
72
- should "support single-execute bodies" do
73
- body = Struct.new(:body) do
74
- def each
75
- yield body.shift until body.empty?
76
- end
77
- def to_ary; end
78
- end.new(%w[one two three])
79
-
80
- app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, body] }
81
- response = content_length(app).call(request)
82
- expected = %w[one two three]
83
- response[1]['Content-Length'].should.equal expected.join.size.to_s
84
- Enumerator.new(response[2]).to_a.should.equal expected
85
- end
86
- end
@@ -1,45 +0,0 @@
1
- require 'rack/content_type'
2
- require 'rack/lint'
3
- require 'rack/mock'
4
-
5
- describe Rack::ContentType do
6
- def content_type(app, *args)
7
- Rack::Lint.new Rack::ContentType.new(app, *args)
8
- end
9
-
10
- def request
11
- Rack::MockRequest.env_for
12
- end
13
-
14
- should "set Content-Type to default text/html if none is set" do
15
- app = lambda { |env| [200, {}, "Hello, World!"] }
16
- headers = content_type(app).call(request)[1]
17
- headers['Content-Type'].should.equal 'text/html'
18
- end
19
-
20
- should "set Content-Type to chosen default if none is set" do
21
- app = lambda { |env| [200, {}, "Hello, World!"] }
22
- headers =
23
- content_type(app, 'application/octet-stream').call(request)[1]
24
- headers['Content-Type'].should.equal 'application/octet-stream'
25
- end
26
-
27
- should "not change Content-Type if it is already set" do
28
- app = lambda { |env| [200, {'Content-Type' => 'foo/bar'}, "Hello, World!"] }
29
- headers = content_type(app).call(request)[1]
30
- headers['Content-Type'].should.equal 'foo/bar'
31
- end
32
-
33
- should "detect Content-Type case insensitive" do
34
- app = lambda { |env| [200, {'CONTENT-Type' => 'foo/bar'}, "Hello, World!"] }
35
- headers = content_type(app).call(request)[1]
36
- headers.to_a.select { |k,v| k.downcase == "content-type" }.
37
- should.equal [["CONTENT-Type","foo/bar"]]
38
- end
39
-
40
- should "not set Content-Type on 304 responses" do
41
- app = lambda { |env| [304, {}, []] }
42
- response = content_type(app, "text/html").call(request)
43
- response[1]['Content-Type'].should.equal nil
44
- end
45
- end
@@ -1,187 +0,0 @@
1
- require 'enumerator'
2
- require 'stringio'
3
- require 'time' # for Time#httpdate
4
- require 'rack/deflater'
5
- require 'rack/lint'
6
- require 'rack/mock'
7
- require 'zlib'
8
-
9
- describe Rack::Deflater do
10
- ::Enumerator = ::Enumerable::Enumerator unless Object.const_defined?(:Enumerator)
11
-
12
- def deflater(app)
13
- Rack::Lint.new Rack::Deflater.new(app)
14
- end
15
-
16
- def build_response(status, body, accept_encoding, headers = {})
17
- body = [body] if body.respond_to? :to_str
18
- app = lambda do |env|
19
- res = [status, {}, body]
20
- res[1]["Content-Type"] = "text/plain" unless res[0] == 304
21
- res
22
- end
23
- request = Rack::MockRequest.env_for("", headers.merge("HTTP_ACCEPT_ENCODING" => accept_encoding))
24
- response = deflater(app).call(request)
25
-
26
- return response
27
- end
28
-
29
- def inflate(buf)
30
- inflater = Zlib::Inflate.new(-Zlib::MAX_WBITS)
31
- inflater.inflate(buf) << inflater.finish
32
- end
33
-
34
- should "be able to deflate bodies that respond to each" do
35
- body = Object.new
36
- class << body; def each; yield("foo"); yield("bar"); end; end
37
-
38
- response = build_response(200, body, "deflate")
39
-
40
- response[0].should.equal(200)
41
- response[1].should.equal({
42
- "Content-Encoding" => "deflate",
43
- "Vary" => "Accept-Encoding",
44
- "Content-Type" => "text/plain"
45
- })
46
- buf = ''
47
- response[2].each { |part| buf << part }
48
- inflate(buf).should.equal("foobar")
49
- end
50
-
51
- should "flush deflated chunks to the client as they become ready" do
52
- body = Object.new
53
- class << body; def each; yield("foo"); yield("bar"); end; end
54
-
55
- response = build_response(200, body, "deflate")
56
-
57
- response[0].should.equal(200)
58
- response[1].should.equal({
59
- "Content-Encoding" => "deflate",
60
- "Vary" => "Accept-Encoding",
61
- "Content-Type" => "text/plain"
62
- })
63
- buf = []
64
- inflater = Zlib::Inflate.new(-Zlib::MAX_WBITS)
65
- response[2].each { |part| buf << inflater.inflate(part) }
66
- buf << inflater.finish
67
- buf.delete_if { |part| part.empty? }
68
- buf.join.should.equal("foobar")
69
- end
70
-
71
- # TODO: This is really just a special case of the above...
72
- should "be able to deflate String bodies" do
73
- response = build_response(200, "Hello world!", "deflate")
74
-
75
- response[0].should.equal(200)
76
- response[1].should.equal({
77
- "Content-Encoding" => "deflate",
78
- "Vary" => "Accept-Encoding",
79
- "Content-Type" => "text/plain"
80
- })
81
- buf = ''
82
- response[2].each { |part| buf << part }
83
- inflate(buf).should.equal("Hello world!")
84
- end
85
-
86
- should "be able to gzip bodies that respond to each" do
87
- body = Object.new
88
- class << body; def each; yield("foo"); yield("bar"); end; end
89
-
90
- response = build_response(200, body, "gzip")
91
-
92
- response[0].should.equal(200)
93
- response[1].should.equal({
94
- "Content-Encoding" => "gzip",
95
- "Vary" => "Accept-Encoding",
96
- "Content-Type" => "text/plain"
97
- })
98
-
99
- buf = ''
100
- response[2].each { |part| buf << part }
101
- io = StringIO.new(buf)
102
- gz = Zlib::GzipReader.new(io)
103
- gz.read.should.equal("foobar")
104
- gz.close
105
- end
106
-
107
- should "flush gzipped chunks to the client as they become ready" do
108
- body = Object.new
109
- class << body; def each; yield("foo"); yield("bar"); end; end
110
-
111
- response = build_response(200, body, "gzip")
112
-
113
- response[0].should.equal(200)
114
- response[1].should.equal({
115
- "Content-Encoding" => "gzip",
116
- "Vary" => "Accept-Encoding",
117
- "Content-Type" => "text/plain"
118
- })
119
- buf = []
120
- inflater = Zlib::Inflate.new(Zlib::MAX_WBITS + 32)
121
- response[2].each { |part| buf << inflater.inflate(part) }
122
- buf << inflater.finish
123
- buf.delete_if { |part| part.empty? }
124
- buf.join.should.equal("foobar")
125
- end
126
-
127
- should "be able to fallback to no deflation" do
128
- response = build_response(200, "Hello world!", "superzip")
129
-
130
- response[0].should.equal(200)
131
- response[1].should.equal({ "Vary" => "Accept-Encoding", "Content-Type" => "text/plain" })
132
- Enumerator.new(response[2]).to_a.should.equal(["Hello world!"])
133
- end
134
-
135
- should "be able to skip when there is no response entity body" do
136
- response = build_response(304, [], "gzip")
137
-
138
- response[0].should.equal(304)
139
- response[1].should.equal({})
140
- Enumerator.new(response[2]).to_a.should.equal([])
141
- end
142
-
143
- should "handle the lack of an acceptable encoding" do
144
- response1 = build_response(200, "Hello world!", "identity;q=0", "PATH_INFO" => "/")
145
- response1[0].should.equal(406)
146
- response1[1].should.equal({"Content-Type" => "text/plain", "Content-Length" => "71"})
147
- Enumerator.new(response1[2]).to_a.should.equal(["An acceptable encoding for the requested resource / could not be found."])
148
-
149
- response2 = build_response(200, "Hello world!", "identity;q=0", "SCRIPT_NAME" => "/foo", "PATH_INFO" => "/bar")
150
- response2[0].should.equal(406)
151
- response2[1].should.equal({"Content-Type" => "text/plain", "Content-Length" => "78"})
152
- Enumerator.new(response2[2]).to_a.should.equal(["An acceptable encoding for the requested resource /foo/bar could not be found."])
153
- end
154
-
155
- should "handle gzip response with Last-Modified header" do
156
- last_modified = Time.now.httpdate
157
-
158
- app = lambda { |env| [200, { "Content-Type" => "text/plain", "Last-Modified" => last_modified }, ["Hello World!"]] }
159
- request = Rack::MockRequest.env_for("", "HTTP_ACCEPT_ENCODING" => "gzip")
160
- response = deflater(app).call(request)
161
-
162
- response[0].should.equal(200)
163
- response[1].should.equal({
164
- "Content-Encoding" => "gzip",
165
- "Vary" => "Accept-Encoding",
166
- "Last-Modified" => last_modified,
167
- "Content-Type" => "text/plain"
168
- })
169
-
170
- buf = ''
171
- response[2].each { |part| buf << part }
172
- io = StringIO.new(buf)
173
- gz = Zlib::GzipReader.new(io)
174
- gz.read.should.equal("Hello World!")
175
- gz.close
176
- end
177
-
178
- should "do nothing when no-transform Cache-Control directive present" do
179
- app = lambda { |env| [200, {'Content-Type' => 'text/plain', 'Cache-Control' => 'no-transform'}, ['Hello World!']] }
180
- request = Rack::MockRequest.env_for("", "HTTP_ACCEPT_ENCODING" => "gzip")
181
- response = deflater(app).call(request)
182
-
183
- response[0].should.equal(200)
184
- response[1].should.not.include "Content-Encoding"
185
- Enumerator.new(response[2]).to_a.join.should.equal("Hello World!")
186
- end
187
- end
@@ -1,88 +0,0 @@
1
- require 'rack/directory'
2
- require 'rack/lint'
3
- require 'rack/mock'
4
-
5
- describe Rack::Directory do
6
- DOCROOT = File.expand_path(File.dirname(__FILE__)) unless defined? DOCROOT
7
- FILE_CATCH = proc{|env| [200, {'Content-Type'=>'text/plain', "Content-Length" => "7"}, ['passed!']] }
8
- app = Rack::Lint.new(Rack::Directory.new(DOCROOT, FILE_CATCH))
9
-
10
- should "serve directory indices" do
11
- res = Rack::MockRequest.new(Rack::Lint.new(app)).
12
- get("/cgi/")
13
-
14
- res.should.be.ok
15
- res.should =~ /<html><head>/
16
- end
17
-
18
- should "pass to app if file found" do
19
- res = Rack::MockRequest.new(Rack::Lint.new(app)).
20
- get("/cgi/test")
21
-
22
- res.should.be.ok
23
- res.should =~ /passed!/
24
- end
25
-
26
- should "serve uri with URL encoded filenames" do
27
- res = Rack::MockRequest.new(Rack::Lint.new(app)).
28
- get("/%63%67%69/") # "/cgi/test"
29
-
30
- res.should.be.ok
31
- res.should =~ /<html><head>/
32
-
33
- res = Rack::MockRequest.new(Rack::Lint.new(app)).
34
- get("/cgi/%74%65%73%74") # "/cgi/test"
35
-
36
- res.should.be.ok
37
- res.should =~ /passed!/
38
- end
39
-
40
- should "not allow directory traversal" do
41
- res = Rack::MockRequest.new(Rack::Lint.new(app)).
42
- get("/cgi/../test")
43
-
44
- res.should.be.forbidden
45
-
46
- res = Rack::MockRequest.new(Rack::Lint.new(app)).
47
- get("/cgi/%2E%2E/test")
48
-
49
- res.should.be.forbidden
50
- end
51
-
52
- should "404 if it can't find the file" do
53
- res = Rack::MockRequest.new(Rack::Lint.new(app)).
54
- get("/cgi/blubb")
55
-
56
- res.should.be.not_found
57
- end
58
-
59
- should "uri escape path parts" do # #265, properly escape file names
60
- mr = Rack::MockRequest.new(Rack::Lint.new(app))
61
-
62
- res = mr.get("/cgi/test%2bdirectory")
63
-
64
- res.should.be.ok
65
- res.body.should =~ %r[/cgi/test%2Bdirectory/test%2Bfile]
66
-
67
- res = mr.get("/cgi/test%2bdirectory/test%2bfile")
68
- res.should.be.ok
69
- end
70
-
71
- should "correctly escape script name" do
72
- app2 = Rack::Builder.new do
73
- map '/script-path' do
74
- run app
75
- end
76
- end
77
-
78
- mr = Rack::MockRequest.new(Rack::Lint.new(app2))
79
-
80
- res = mr.get("/script-path/cgi/test%2bdirectory")
81
-
82
- res.should.be.ok
83
- res.body.should =~ %r[/script-path/cgi/test%2Bdirectory/test%2Bfile]
84
-
85
- res = mr.get("/script-path/cgi/test%2bdirectory/test%2bfile")
86
- res.should.be.ok
87
- end
88
- end
data/test/spec_etag.rb DELETED
@@ -1,98 +0,0 @@
1
- require 'rack/etag'
2
- require 'rack/lint'
3
- require 'rack/mock'
4
- require 'time'
5
-
6
- describe Rack::ETag do
7
- def etag(app, *args)
8
- Rack::Lint.new Rack::ETag.new(app, *args)
9
- end
10
-
11
- def request
12
- Rack::MockRequest.env_for
13
- end
14
-
15
- def sendfile_body
16
- res = ['Hello World']
17
- def res.to_path ; "/tmp/hello.txt" ; end
18
- res
19
- end
20
-
21
- should "set ETag if none is set if status is 200" do
22
- app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, ["Hello, World!"]] }
23
- response = etag(app).call(request)
24
- response[1]['ETag'].should.equal "\"65a8e27d8879283831b664bd8b7f0ad4\""
25
- end
26
-
27
- should "set ETag if none is set if status is 201" do
28
- app = lambda { |env| [201, {'Content-Type' => 'text/plain'}, ["Hello, World!"]] }
29
- response = etag(app).call(request)
30
- response[1]['ETag'].should.equal "\"65a8e27d8879283831b664bd8b7f0ad4\""
31
- end
32
-
33
- should "set Cache-Control to 'max-age=0, private, must-revalidate' (default) if none is set" do
34
- app = lambda { |env| [201, {'Content-Type' => 'text/plain'}, ["Hello, World!"]] }
35
- response = etag(app).call(request)
36
- response[1]['Cache-Control'].should.equal 'max-age=0, private, must-revalidate'
37
- end
38
-
39
- should "set Cache-Control to chosen one if none is set" do
40
- app = lambda { |env| [201, {'Content-Type' => 'text/plain'}, ["Hello, World!"]] }
41
- response = etag(app, nil, 'public').call(request)
42
- response[1]['Cache-Control'].should.equal 'public'
43
- end
44
-
45
- should "set a given Cache-Control even if digest could not be calculated" do
46
- app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, []] }
47
- response = etag(app, 'no-cache').call(request)
48
- response[1]['Cache-Control'].should.equal 'no-cache'
49
- end
50
-
51
- should "not set Cache-Control if it is already set" do
52
- app = lambda { |env| [201, {'Content-Type' => 'text/plain', 'Cache-Control' => 'public'}, ["Hello, World!"]] }
53
- response = etag(app).call(request)
54
- response[1]['Cache-Control'].should.equal 'public'
55
- end
56
-
57
- should "not set Cache-Control if directive isn't present" do
58
- app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, ["Hello, World!"]] }
59
- response = etag(app, nil, nil).call(request)
60
- response[1]['Cache-Control'].should.equal nil
61
- end
62
-
63
- should "not change ETag if it is already set" do
64
- app = lambda { |env| [200, {'Content-Type' => 'text/plain', 'ETag' => '"abc"'}, ["Hello, World!"]] }
65
- response = etag(app).call(request)
66
- response[1]['ETag'].should.equal "\"abc\""
67
- end
68
-
69
- should "not set ETag if body is empty" do
70
- app = lambda { |env| [200, {'Content-Type' => 'text/plain', 'Last-Modified' => Time.now.httpdate}, []] }
71
- response = etag(app).call(request)
72
- response[1]['ETag'].should.be.nil
73
- end
74
-
75
- should "not set ETag if Last-Modified is set" do
76
- app = lambda { |env| [200, {'Content-Type' => 'text/plain', 'Last-Modified' => Time.now.httpdate}, ["Hello, World!"]] }
77
- response = etag(app).call(request)
78
- response[1]['ETag'].should.be.nil
79
- end
80
-
81
- should "not set ETag if a sendfile_body is given" do
82
- app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, sendfile_body] }
83
- response = etag(app).call(request)
84
- response[1]['ETag'].should.be.nil
85
- end
86
-
87
- should "not set ETag if a status is not 200 or 201" do
88
- app = lambda { |env| [401, {'Content-Type' => 'text/plain'}, ['Access denied.']] }
89
- response = etag(app).call(request)
90
- response[1]['ETag'].should.be.nil
91
- end
92
-
93
- should "not set ETag if no-cache is given" do
94
- app = lambda { |env| [200, {'Content-Type' => 'text/plain', 'Cache-Control' => 'no-cache, must-revalidate'}, ['Hello, World!']] }
95
- response = etag(app).call(request)
96
- response[1]['ETag'].should.be.nil
97
- end
98
- end
data/test/spec_fastcgi.rb DELETED
@@ -1,107 +0,0 @@
1
- begin
2
- require File.expand_path('../testrequest', __FILE__)
3
- require 'rack/handler/fastcgi'
4
-
5
- describe Rack::Handler::FastCGI do
6
- extend TestRequest::Helpers
7
-
8
- @host = '127.0.0.1'
9
- @port = 9203
10
-
11
- if `which lighttpd` && !$?.success?
12
- raise "lighttpd not found"
13
- end
14
-
15
- # Keep this first.
16
- $pid = fork {
17
- ENV['RACK_ENV'] = 'deployment'
18
- ENV['RUBYLIB'] = [
19
- File.expand_path('../../lib', __FILE__),
20
- ENV['RUBYLIB'],
21
- ].compact.join(':')
22
-
23
- Dir.chdir(File.expand_path("../cgi", __FILE__)) do
24
- exec "lighttpd -D -f lighttpd.conf"
25
- end
26
- }
27
-
28
- should "respond" do
29
- sleep 1
30
- GET("/test")
31
- response.should.not.be.nil
32
- end
33
-
34
- should "respond via rackup server" do
35
- GET("/sample_rackup.ru")
36
- status.should.equal 200
37
- end
38
-
39
- should "be a lighttpd" do
40
- GET("/test.fcgi")
41
- status.should.equal 200
42
- response["SERVER_SOFTWARE"].should =~ /lighttpd/
43
- response["HTTP_VERSION"].should.equal "HTTP/1.1"
44
- response["SERVER_PROTOCOL"].should.equal "HTTP/1.1"
45
- response["SERVER_PORT"].should.equal @port.to_s
46
- response["SERVER_NAME"].should.equal @host
47
- end
48
-
49
- should "have rack headers" do
50
- GET("/test.fcgi")
51
- response["rack.version"].should.equal [1,1]
52
- response["rack.multithread"].should.be.false
53
- response["rack.multiprocess"].should.be.true
54
- response["rack.run_once"].should.be.false
55
- end
56
-
57
- should "have CGI headers on GET" do
58
- GET("/test.fcgi")
59
- response["REQUEST_METHOD"].should.equal "GET"
60
- response["SCRIPT_NAME"].should.equal "/test.fcgi"
61
- response["REQUEST_PATH"].should.equal "/"
62
- response["PATH_INFO"].should.equal ""
63
- response["QUERY_STRING"].should.equal ""
64
- response["test.postdata"].should.equal ""
65
-
66
- GET("/test.fcgi/foo?quux=1")
67
- response["REQUEST_METHOD"].should.equal "GET"
68
- response["SCRIPT_NAME"].should.equal "/test.fcgi"
69
- response["REQUEST_PATH"].should.equal "/"
70
- response["PATH_INFO"].should.equal "/foo"
71
- response["QUERY_STRING"].should.equal "quux=1"
72
- end
73
-
74
- should "have CGI headers on POST" do
75
- POST("/test.fcgi", {"rack-form-data" => "23"}, {'X-test-header' => '42'})
76
- status.should.equal 200
77
- response["REQUEST_METHOD"].should.equal "POST"
78
- response["SCRIPT_NAME"].should.equal "/test.fcgi"
79
- response["REQUEST_PATH"].should.equal "/"
80
- response["QUERY_STRING"].should.equal ""
81
- response["HTTP_X_TEST_HEADER"].should.equal "42"
82
- response["test.postdata"].should.equal "rack-form-data=23"
83
- end
84
-
85
- should "support HTTP auth" do
86
- GET("/test.fcgi", {:user => "ruth", :passwd => "secret"})
87
- response["HTTP_AUTHORIZATION"].should.equal "Basic cnV0aDpzZWNyZXQ="
88
- end
89
-
90
- should "set status" do
91
- GET("/test.fcgi?secret")
92
- status.should.equal 403
93
- response["rack.url_scheme"].should.equal "http"
94
- end
95
-
96
- # Keep this last.
97
- should "shutdown" do
98
- Process.kill 15, $pid
99
- Process.wait($pid).should.equal $pid
100
- end
101
- end
102
-
103
- rescue RuntimeError
104
- $stderr.puts "Skipping Rack::Handler::FastCGI tests (lighttpd is required). Install lighttpd and try again."
105
- rescue LoadError
106
- $stderr.puts "Skipping Rack::Handler::FastCGI tests (FCGI is required). `gem install fcgi` and try again."
107
- end