rack 1.1.6 → 1.6.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (212) hide show
  1. checksums.yaml +7 -0
  2. data/COPYING +1 -1
  3. data/HISTORY.md +375 -0
  4. data/KNOWN-ISSUES +23 -0
  5. data/README.rdoc +312 -0
  6. data/Rakefile +124 -0
  7. data/SPEC +125 -32
  8. data/contrib/rack.png +0 -0
  9. data/contrib/rack.svg +150 -0
  10. data/contrib/rack_logo.svg +1 -1
  11. data/contrib/rdoc.css +412 -0
  12. data/example/protectedlobster.rb +1 -1
  13. data/lib/rack/auth/abstract/handler.rb +4 -4
  14. data/lib/rack/auth/abstract/request.rb +7 -5
  15. data/lib/rack/auth/basic.rb +1 -1
  16. data/lib/rack/auth/digest/md5.rb +7 -3
  17. data/lib/rack/auth/digest/nonce.rb +1 -1
  18. data/lib/rack/auth/digest/params.rb +7 -9
  19. data/lib/rack/auth/digest/request.rb +10 -9
  20. data/lib/rack/backports/uri/common_18.rb +56 -0
  21. data/lib/rack/backports/uri/common_192.rb +52 -0
  22. data/lib/rack/backports/uri/common_193.rb +29 -0
  23. data/lib/rack/body_proxy.rb +39 -0
  24. data/lib/rack/builder.rb +106 -22
  25. data/lib/rack/cascade.rb +17 -6
  26. data/lib/rack/chunked.rb +44 -24
  27. data/lib/rack/commonlogger.rb +36 -13
  28. data/lib/rack/conditionalget.rb +49 -17
  29. data/lib/rack/config.rb +5 -0
  30. data/lib/rack/content_length.rb +14 -6
  31. data/lib/rack/content_type.rb +7 -1
  32. data/lib/rack/deflater.rb +73 -15
  33. data/lib/rack/directory.rb +18 -8
  34. data/lib/rack/etag.rb +59 -9
  35. data/lib/rack/file.rb +106 -44
  36. data/lib/rack/handler/cgi.rb +11 -11
  37. data/lib/rack/handler/fastcgi.rb +18 -6
  38. data/lib/rack/handler/lsws.rb +2 -4
  39. data/lib/rack/handler/mongrel.rb +22 -6
  40. data/lib/rack/handler/scgi.rb +16 -8
  41. data/lib/rack/handler/thin.rb +19 -4
  42. data/lib/rack/handler/webrick.rb +72 -19
  43. data/lib/rack/handler.rb +47 -14
  44. data/lib/rack/head.rb +10 -2
  45. data/lib/rack/lint.rb +260 -75
  46. data/lib/rack/lobster.rb +13 -8
  47. data/lib/rack/lock.rb +13 -3
  48. data/lib/rack/logger.rb +0 -2
  49. data/lib/rack/methodoverride.rb +27 -8
  50. data/lib/rack/mime.rb +625 -167
  51. data/lib/rack/mock.rb +78 -53
  52. data/lib/rack/multipart/generator.rb +93 -0
  53. data/lib/rack/multipart/parser.rb +253 -0
  54. data/lib/rack/multipart/uploaded_file.rb +34 -0
  55. data/lib/rack/multipart.rb +34 -0
  56. data/lib/rack/nulllogger.rb +21 -2
  57. data/lib/rack/recursive.rb +10 -5
  58. data/lib/rack/reloader.rb +3 -2
  59. data/lib/rack/request.rb +201 -74
  60. data/lib/rack/response.rb +41 -28
  61. data/lib/rack/rewindable_input.rb +15 -11
  62. data/lib/rack/runtime.rb +16 -3
  63. data/lib/rack/sendfile.rb +47 -29
  64. data/lib/rack/server.rb +223 -47
  65. data/lib/rack/session/abstract/id.rb +289 -30
  66. data/lib/rack/session/cookie.rb +133 -44
  67. data/lib/rack/session/memcache.rb +30 -56
  68. data/lib/rack/session/pool.rb +19 -43
  69. data/lib/rack/showexceptions.rb +53 -15
  70. data/lib/rack/showstatus.rb +14 -7
  71. data/lib/rack/static.rb +124 -12
  72. data/lib/rack/tempfile_reaper.rb +22 -0
  73. data/lib/rack/urlmap.rb +49 -15
  74. data/lib/rack/utils/okjson.rb +600 -0
  75. data/lib/rack/utils.rb +363 -361
  76. data/lib/rack.rb +17 -23
  77. data/rack.gemspec +11 -20
  78. data/test/builder/anything.rb +5 -0
  79. data/test/builder/comment.ru +4 -0
  80. data/test/builder/end.ru +5 -0
  81. data/test/builder/line.ru +1 -0
  82. data/test/builder/options.ru +2 -0
  83. data/test/cgi/assets/folder/test.js +1 -0
  84. data/test/cgi/assets/fonts/font.eot +1 -0
  85. data/test/cgi/assets/images/image.png +1 -0
  86. data/test/cgi/assets/index.html +1 -0
  87. data/test/cgi/assets/javascripts/app.js +1 -0
  88. data/test/cgi/assets/stylesheets/app.css +1 -0
  89. data/test/cgi/lighttpd.conf +26 -0
  90. data/test/cgi/rackup_stub.rb +6 -0
  91. data/test/cgi/sample_rackup.ru +5 -0
  92. data/test/cgi/test +9 -0
  93. data/test/cgi/test+directory/test+file +1 -0
  94. data/test/cgi/test.fcgi +8 -0
  95. data/test/cgi/test.ru +5 -0
  96. data/test/gemloader.rb +10 -0
  97. data/test/multipart/bad_robots +259 -0
  98. data/test/multipart/binary +0 -0
  99. data/test/multipart/content_type_and_no_filename +6 -0
  100. data/test/multipart/empty +10 -0
  101. data/test/multipart/fail_16384_nofile +814 -0
  102. data/test/multipart/file1.txt +1 -0
  103. data/test/multipart/filename_and_modification_param +7 -0
  104. data/test/multipart/filename_and_no_name +6 -0
  105. data/test/multipart/filename_with_escaped_quotes +6 -0
  106. data/test/multipart/filename_with_escaped_quotes_and_modification_param +7 -0
  107. data/test/multipart/filename_with_null_byte +7 -0
  108. data/test/multipart/filename_with_percent_escaped_quotes +6 -0
  109. data/test/multipart/filename_with_unescaped_percentages +6 -0
  110. data/test/multipart/filename_with_unescaped_percentages2 +6 -0
  111. data/test/multipart/filename_with_unescaped_percentages3 +6 -0
  112. data/test/multipart/filename_with_unescaped_quotes +6 -0
  113. data/test/multipart/ie +6 -0
  114. data/test/multipart/invalid_character +6 -0
  115. data/test/multipart/mixed_files +21 -0
  116. data/test/multipart/nested +10 -0
  117. data/test/multipart/none +9 -0
  118. data/test/multipart/semicolon +6 -0
  119. data/test/multipart/text +15 -0
  120. data/test/multipart/three_files_three_fields +31 -0
  121. data/test/multipart/webkit +32 -0
  122. data/test/rackup/config.ru +31 -0
  123. data/test/registering_handler/rack/handler/registering_myself.rb +8 -0
  124. data/test/{spec_rack_auth_basic.rb → spec_auth_basic.rb} +23 -15
  125. data/test/{spec_rack_auth_digest.rb → spec_auth_digest.rb} +56 -29
  126. data/test/spec_body_proxy.rb +85 -0
  127. data/test/spec_builder.rb +223 -0
  128. data/test/{spec_rack_cascade.rb → spec_cascade.rb} +28 -15
  129. data/test/{spec_rack_cgi.rb → spec_cgi.rb} +44 -31
  130. data/test/spec_chunked.rb +101 -0
  131. data/test/spec_commonlogger.rb +93 -0
  132. data/test/spec_conditionalget.rb +102 -0
  133. data/test/{spec_rack_config.rb → spec_config.rb} +6 -8
  134. data/test/spec_content_length.rb +85 -0
  135. data/test/spec_content_type.rb +45 -0
  136. data/test/spec_deflater.rb +339 -0
  137. data/test/{spec_rack_directory.rb → spec_directory.rb} +37 -10
  138. data/test/spec_etag.rb +107 -0
  139. data/test/{spec_rack_fastcgi.rb → spec_fastcgi.rb} +47 -29
  140. data/test/spec_file.rb +221 -0
  141. data/test/spec_handler.rb +72 -0
  142. data/test/spec_head.rb +45 -0
  143. data/test/{spec_rack_lint.rb → spec_lint.rb} +82 -60
  144. data/test/spec_lobster.rb +58 -0
  145. data/test/spec_lock.rb +164 -0
  146. data/test/spec_logger.rb +23 -0
  147. data/test/spec_methodoverride.rb +95 -0
  148. data/test/spec_mime.rb +51 -0
  149. data/test/{spec_rack_mock.rb → spec_mock.rb} +92 -38
  150. data/test/{spec_rack_mongrel.rb → spec_mongrel.rb} +46 -53
  151. data/test/spec_multipart.rb +600 -0
  152. data/test/spec_nulllogger.rb +20 -0
  153. data/test/spec_recursive.rb +72 -0
  154. data/test/spec_request.rb +1227 -0
  155. data/test/spec_response.rb +407 -0
  156. data/test/spec_rewindable_input.rb +118 -0
  157. data/test/spec_runtime.rb +49 -0
  158. data/test/spec_sendfile.rb +130 -0
  159. data/test/spec_server.rb +167 -0
  160. data/test/spec_session_abstract_id.rb +53 -0
  161. data/test/spec_session_cookie.rb +410 -0
  162. data/test/{spec_rack_session_memcache.rb → spec_session_memcache.rb} +119 -71
  163. data/test/{spec_rack_session_pool.rb → spec_session_pool.rb} +106 -69
  164. data/test/spec_showexceptions.rb +85 -0
  165. data/test/spec_showstatus.rb +103 -0
  166. data/test/spec_static.rb +145 -0
  167. data/test/spec_tempfile_reaper.rb +63 -0
  168. data/test/{spec_rack_thin.rb → spec_thin.rb} +35 -35
  169. data/test/{spec_rack_urlmap.rb → spec_urlmap.rb} +40 -19
  170. data/test/spec_utils.rb +647 -0
  171. data/test/spec_version.rb +17 -0
  172. data/test/spec_webrick.rb +184 -0
  173. data/test/static/another/index.html +1 -0
  174. data/test/static/index.html +1 -0
  175. data/test/testrequest.rb +78 -0
  176. data/test/unregistered_handler/rack/handler/unregistered.rb +7 -0
  177. data/test/unregistered_handler/rack/handler/unregistered_long_one.rb +7 -0
  178. metadata +220 -239
  179. data/RDOX +0 -0
  180. data/README +0 -592
  181. data/lib/rack/adapter/camping.rb +0 -22
  182. data/test/spec_auth.rb +0 -57
  183. data/test/spec_rack_builder.rb +0 -84
  184. data/test/spec_rack_camping.rb +0 -55
  185. data/test/spec_rack_chunked.rb +0 -62
  186. data/test/spec_rack_commonlogger.rb +0 -61
  187. data/test/spec_rack_conditionalget.rb +0 -41
  188. data/test/spec_rack_content_length.rb +0 -43
  189. data/test/spec_rack_content_type.rb +0 -30
  190. data/test/spec_rack_deflater.rb +0 -127
  191. data/test/spec_rack_etag.rb +0 -17
  192. data/test/spec_rack_file.rb +0 -75
  193. data/test/spec_rack_handler.rb +0 -43
  194. data/test/spec_rack_head.rb +0 -30
  195. data/test/spec_rack_lobster.rb +0 -45
  196. data/test/spec_rack_lock.rb +0 -38
  197. data/test/spec_rack_logger.rb +0 -21
  198. data/test/spec_rack_methodoverride.rb +0 -60
  199. data/test/spec_rack_nulllogger.rb +0 -13
  200. data/test/spec_rack_recursive.rb +0 -77
  201. data/test/spec_rack_request.rb +0 -594
  202. data/test/spec_rack_response.rb +0 -221
  203. data/test/spec_rack_rewindable_input.rb +0 -118
  204. data/test/spec_rack_runtime.rb +0 -35
  205. data/test/spec_rack_sendfile.rb +0 -86
  206. data/test/spec_rack_session_cookie.rb +0 -92
  207. data/test/spec_rack_showexceptions.rb +0 -21
  208. data/test/spec_rack_showstatus.rb +0 -72
  209. data/test/spec_rack_static.rb +0 -37
  210. data/test/spec_rack_utils.rb +0 -557
  211. data/test/spec_rack_webrick.rb +0 -130
  212. data/test/spec_rackup.rb +0 -164
@@ -1,594 +0,0 @@
1
- require 'test/spec'
2
- require 'stringio'
3
-
4
- require 'rack/request'
5
- require 'rack/mock'
6
-
7
- context "Rack::Request" do
8
- specify "wraps the rack variables" do
9
- req = Rack::Request.new(Rack::MockRequest.env_for("http://example.com:8080/"))
10
-
11
- req.body.should.respond_to? :gets
12
- req.scheme.should.equal "http"
13
- req.request_method.should.equal "GET"
14
-
15
- req.should.be.get
16
- req.should.not.be.post
17
- req.should.not.be.put
18
- req.should.not.be.delete
19
- req.should.not.be.head
20
-
21
- req.script_name.should.equal ""
22
- req.path_info.should.equal "/"
23
- req.query_string.should.equal ""
24
-
25
- req.host.should.equal "example.com"
26
- req.port.should.equal 8080
27
-
28
- req.content_length.should.equal "0"
29
- req.content_type.should.be.nil
30
- end
31
-
32
- specify "can figure out the correct host" do
33
- req = Rack::Request.new \
34
- Rack::MockRequest.env_for("/", "HTTP_HOST" => "www2.example.org")
35
- req.host.should.equal "www2.example.org"
36
-
37
- req = Rack::Request.new \
38
- Rack::MockRequest.env_for("/", "SERVER_NAME" => "example.org", "SERVER_PORT" => "9292")
39
- req.host.should.equal "example.org"
40
-
41
- req = Rack::Request.new \
42
- Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org:9292")
43
- req.host.should.equal "example.org"
44
-
45
- env = Rack::MockRequest.env_for("/", "SERVER_ADDR" => "192.168.1.1", "SERVER_PORT" => "9292")
46
- env.delete("SERVER_NAME")
47
- req = Rack::Request.new(env)
48
- req.host.should.equal "192.168.1.1"
49
-
50
- env = Rack::MockRequest.env_for("/")
51
- env.delete("SERVER_NAME")
52
- req = Rack::Request.new(env)
53
- req.host.should.equal ""
54
- end
55
-
56
- specify "can parse the query string" do
57
- req = Rack::Request.new(Rack::MockRequest.env_for("/?foo=bar&quux=bla"))
58
- req.query_string.should.equal "foo=bar&quux=bla"
59
- req.GET.should.equal "foo" => "bar", "quux" => "bla"
60
- req.POST.should.be.empty
61
- req.params.should.equal "foo" => "bar", "quux" => "bla"
62
- end
63
-
64
- specify "raises if rack.input is missing" do
65
- req = Rack::Request.new({})
66
- lambda { req.POST }.should.raise(RuntimeError)
67
- end
68
-
69
- specify "can parse POST data when method is POST and no Content-Type given" do
70
- req = Rack::Request.new \
71
- Rack::MockRequest.env_for("/?foo=quux",
72
- "REQUEST_METHOD" => 'POST',
73
- :input => "foo=bar&quux=bla")
74
- req.content_type.should.be.nil
75
- req.media_type.should.be.nil
76
- req.query_string.should.equal "foo=quux"
77
- req.GET.should.equal "foo" => "quux"
78
- req.POST.should.equal "foo" => "bar", "quux" => "bla"
79
- req.params.should.equal "foo" => "bar", "quux" => "bla"
80
- end
81
-
82
- specify "limit the keys from the GET query string" do
83
- env = Rack::MockRequest.env_for("/?foo=bar")
84
-
85
- old, Rack::Utils.key_space_limit = Rack::Utils.key_space_limit, 1
86
- begin
87
- req = Rack::Request.new(env)
88
- lambda { req.GET }.should.raise(RangeError)
89
- ensure
90
- Rack::Utils.key_space_limit = old
91
- end
92
- end
93
-
94
- specify "limit the keys from the POST form data" do
95
- env = Rack::MockRequest.env_for("",
96
- "REQUEST_METHOD" => 'POST',
97
- :input => "foo=bar&quux=bla")
98
-
99
- old, Rack::Utils.key_space_limit = Rack::Utils.key_space_limit, 1
100
- begin
101
- req = Rack::Request.new(env)
102
- lambda { req.POST }.should.raise(RangeError)
103
- ensure
104
- Rack::Utils.key_space_limit = old
105
- end
106
- end
107
-
108
- specify "can parse POST data with explicit content type regardless of method" do
109
- req = Rack::Request.new \
110
- Rack::MockRequest.env_for("/",
111
- "CONTENT_TYPE" => 'application/x-www-form-urlencoded;foo=bar',
112
- :input => "foo=bar&quux=bla")
113
- req.content_type.should.equal 'application/x-www-form-urlencoded;foo=bar'
114
- req.media_type.should.equal 'application/x-www-form-urlencoded'
115
- req.media_type_params['foo'].should.equal 'bar'
116
- req.POST.should.equal "foo" => "bar", "quux" => "bla"
117
- req.params.should.equal "foo" => "bar", "quux" => "bla"
118
- end
119
-
120
- specify "does not parse POST data when media type is not form-data" do
121
- req = Rack::Request.new \
122
- Rack::MockRequest.env_for("/?foo=quux",
123
- "REQUEST_METHOD" => 'POST',
124
- "CONTENT_TYPE" => 'text/plain;charset=utf-8',
125
- :input => "foo=bar&quux=bla")
126
- req.content_type.should.equal 'text/plain;charset=utf-8'
127
- req.media_type.should.equal 'text/plain'
128
- req.media_type_params['charset'].should.equal 'utf-8'
129
- req.POST.should.be.empty
130
- req.params.should.equal "foo" => "quux"
131
- req.body.read.should.equal "foo=bar&quux=bla"
132
- end
133
-
134
- specify "can parse POST data on PUT when media type is form-data" do
135
- req = Rack::Request.new \
136
- Rack::MockRequest.env_for("/?foo=quux",
137
- "REQUEST_METHOD" => 'PUT',
138
- "CONTENT_TYPE" => 'application/x-www-form-urlencoded',
139
- :input => "foo=bar&quux=bla")
140
- req.POST.should.equal "foo" => "bar", "quux" => "bla"
141
- req.body.read.should.equal "foo=bar&quux=bla"
142
- end
143
-
144
- specify "rewinds input after parsing POST data" do
145
- input = StringIO.new("foo=bar&quux=bla")
146
- req = Rack::Request.new \
147
- Rack::MockRequest.env_for("/",
148
- "CONTENT_TYPE" => 'application/x-www-form-urlencoded;foo=bar',
149
- :input => input)
150
- req.params.should.equal "foo" => "bar", "quux" => "bla"
151
- input.read.should.equal "foo=bar&quux=bla"
152
- end
153
-
154
- specify "cleans up Safari's ajax POST body" do
155
- req = Rack::Request.new \
156
- Rack::MockRequest.env_for("/",
157
- 'REQUEST_METHOD' => 'POST', :input => "foo=bar&quux=bla\0")
158
- req.POST.should.equal "foo" => "bar", "quux" => "bla"
159
- end
160
-
161
- specify "can get value by key from params with #[]" do
162
- req = Rack::Request.new \
163
- Rack::MockRequest.env_for("?foo=quux")
164
- req['foo'].should.equal 'quux'
165
- req[:foo].should.equal 'quux'
166
- end
167
-
168
- specify "can set value to key on params with #[]=" do
169
- req = Rack::Request.new \
170
- Rack::MockRequest.env_for("?foo=duh")
171
- req['foo'].should.equal 'duh'
172
- req[:foo].should.equal 'duh'
173
- req.params.should.equal 'foo' => 'duh'
174
-
175
- req['foo'] = 'bar'
176
- req.params.should.equal 'foo' => 'bar'
177
- req['foo'].should.equal 'bar'
178
- req[:foo].should.equal 'bar'
179
-
180
- req[:foo] = 'jaz'
181
- req.params.should.equal 'foo' => 'jaz'
182
- req['foo'].should.equal 'jaz'
183
- req[:foo].should.equal 'jaz'
184
- end
185
-
186
- specify "values_at answers values by keys in order given" do
187
- req = Rack::Request.new \
188
- Rack::MockRequest.env_for("?foo=baz&wun=der&bar=ful")
189
- req.values_at('foo').should.equal ['baz']
190
- req.values_at('foo', 'wun').should.equal ['baz', 'der']
191
- req.values_at('bar', 'foo', 'wun').should.equal ['ful', 'baz', 'der']
192
- end
193
-
194
- specify "referrer should be extracted correct" do
195
- req = Rack::Request.new \
196
- Rack::MockRequest.env_for("/", "HTTP_REFERER" => "/some/path")
197
- req.referer.should.equal "/some/path"
198
-
199
- req = Rack::Request.new \
200
- Rack::MockRequest.env_for("/")
201
- req.referer.should.equal "/"
202
- end
203
-
204
- specify "user agent should be extracted correct" do
205
- req = Rack::Request.new \
206
- Rack::MockRequest.env_for("/", "HTTP_USER_AGENT" => "Mozilla/4.0 (compatible)")
207
- req.user_agent.should.equal "Mozilla/4.0 (compatible)"
208
-
209
- req = Rack::Request.new \
210
- Rack::MockRequest.env_for("/")
211
- req.user_agent.should.equal nil
212
- end
213
-
214
- specify "can cache, but invalidates the cache" do
215
- req = Rack::Request.new \
216
- Rack::MockRequest.env_for("/?foo=quux",
217
- "CONTENT_TYPE" => "application/x-www-form-urlencoded",
218
- :input => "foo=bar&quux=bla")
219
- req.GET.should.equal "foo" => "quux"
220
- req.GET.should.equal "foo" => "quux"
221
- req.env["QUERY_STRING"] = "bla=foo"
222
- req.GET.should.equal "bla" => "foo"
223
- req.GET.should.equal "bla" => "foo"
224
-
225
- req.POST.should.equal "foo" => "bar", "quux" => "bla"
226
- req.POST.should.equal "foo" => "bar", "quux" => "bla"
227
- req.env["rack.input"] = StringIO.new("foo=bla&quux=bar")
228
- req.POST.should.equal "foo" => "bla", "quux" => "bar"
229
- req.POST.should.equal "foo" => "bla", "quux" => "bar"
230
- end
231
-
232
- specify "can figure out if called via XHR" do
233
- req = Rack::Request.new(Rack::MockRequest.env_for(""))
234
- req.should.not.be.xhr
235
-
236
- req = Rack::Request.new \
237
- Rack::MockRequest.env_for("", "HTTP_X_REQUESTED_WITH" => "XMLHttpRequest")
238
- req.should.be.xhr
239
- end
240
-
241
- specify "can parse cookies" do
242
- req = Rack::Request.new \
243
- Rack::MockRequest.env_for("", "HTTP_COOKIE" => "foo=bar;quux=h&m")
244
- req.cookies.should.equal "foo" => "bar", "quux" => "h&m"
245
- req.cookies.should.equal "foo" => "bar", "quux" => "h&m"
246
- req.env.delete("HTTP_COOKIE")
247
- req.cookies.should.equal({})
248
- end
249
-
250
- specify "parses cookies according to RFC 2109" do
251
- req = Rack::Request.new \
252
- Rack::MockRequest.env_for('', 'HTTP_COOKIE' => 'foo=bar;foo=car')
253
- req.cookies.should.equal 'foo' => 'bar'
254
- end
255
-
256
- specify "provides setters" do
257
- req = Rack::Request.new(e=Rack::MockRequest.env_for(""))
258
- req.script_name.should.equal ""
259
- req.script_name = "/foo"
260
- req.script_name.should.equal "/foo"
261
- e["SCRIPT_NAME"].should.equal "/foo"
262
-
263
- req.path_info.should.equal "/"
264
- req.path_info = "/foo"
265
- req.path_info.should.equal "/foo"
266
- e["PATH_INFO"].should.equal "/foo"
267
- end
268
-
269
- specify "provides the original env" do
270
- req = Rack::Request.new(e=Rack::MockRequest.env_for(""))
271
- req.env.should.be e
272
- end
273
-
274
- specify "can restore the URL" do
275
- Rack::Request.new(Rack::MockRequest.env_for("")).url.
276
- should.equal "http://example.org/"
277
- Rack::Request.new(Rack::MockRequest.env_for("", "SCRIPT_NAME" => "/foo")).url.
278
- should.equal "http://example.org/foo/"
279
- Rack::Request.new(Rack::MockRequest.env_for("/foo")).url.
280
- should.equal "http://example.org/foo"
281
- Rack::Request.new(Rack::MockRequest.env_for("?foo")).url.
282
- should.equal "http://example.org/?foo"
283
- Rack::Request.new(Rack::MockRequest.env_for("http://example.org:8080/")).url.
284
- should.equal "http://example.org:8080/"
285
- Rack::Request.new(Rack::MockRequest.env_for("https://example.org/")).url.
286
- should.equal "https://example.org/"
287
-
288
- Rack::Request.new(Rack::MockRequest.env_for("https://example.com:8080/foo?foo")).url.
289
- should.equal "https://example.com:8080/foo?foo"
290
- end
291
-
292
- specify "can restore the full path" do
293
- Rack::Request.new(Rack::MockRequest.env_for("")).fullpath.
294
- should.equal "/"
295
- Rack::Request.new(Rack::MockRequest.env_for("", "SCRIPT_NAME" => "/foo")).fullpath.
296
- should.equal "/foo/"
297
- Rack::Request.new(Rack::MockRequest.env_for("/foo")).fullpath.
298
- should.equal "/foo"
299
- Rack::Request.new(Rack::MockRequest.env_for("?foo")).fullpath.
300
- should.equal "/?foo"
301
- Rack::Request.new(Rack::MockRequest.env_for("http://example.org:8080/")).fullpath.
302
- should.equal "/"
303
- Rack::Request.new(Rack::MockRequest.env_for("https://example.org/")).fullpath.
304
- should.equal "/"
305
-
306
- Rack::Request.new(Rack::MockRequest.env_for("https://example.com:8080/foo?foo")).fullpath.
307
- should.equal "/foo?foo"
308
- end
309
-
310
- specify "can handle multiple media type parameters" do
311
- req = Rack::Request.new \
312
- Rack::MockRequest.env_for("/",
313
- "CONTENT_TYPE" => 'text/plain; foo=BAR,baz=bizzle dizzle;BLING=bam')
314
- req.should.not.be.form_data
315
- req.media_type_params.should.include 'foo'
316
- req.media_type_params['foo'].should.equal 'BAR'
317
- req.media_type_params.should.include 'baz'
318
- req.media_type_params['baz'].should.equal 'bizzle dizzle'
319
- req.media_type_params.should.not.include 'BLING'
320
- req.media_type_params.should.include 'bling'
321
- req.media_type_params['bling'].should.equal 'bam'
322
- end
323
-
324
- specify "raise RangeError if the key space is exhausted" do
325
- input = <<EOF
326
- --AaB03x\r
327
- Content-Disposition: form-data; name="text"\r
328
- Content-Type: text/plain; charset=US-ASCII\r
329
- \r
330
- contents\r
331
- --AaB03x--\r
332
- EOF
333
-
334
- env = Rack::MockRequest.env_for("/",
335
- "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
336
- "CONTENT_LENGTH" => input.size,
337
- :input => input)
338
-
339
- old, Rack::Utils.key_space_limit = Rack::Utils.key_space_limit, 1
340
- begin
341
- lambda { Rack::Utils::Multipart.parse_multipart(env) }.should.raise(RangeError)
342
- ensure
343
- Rack::Utils.key_space_limit = old
344
- end
345
- end
346
-
347
- specify "can parse multipart form data" do
348
- # Adapted from RFC 1867.
349
- input = <<EOF
350
- --AaB03x\r
351
- content-disposition: form-data; name="reply"\r
352
- \r
353
- yes\r
354
- --AaB03x\r
355
- content-disposition: form-data; name="fileupload"; filename="dj.jpg"\r
356
- Content-Type: image/jpeg\r
357
- Content-Transfer-Encoding: base64\r
358
- \r
359
- /9j/4AAQSkZJRgABAQAAAQABAAD//gA+Q1JFQVRPUjogZ2QtanBlZyB2MS4wICh1c2luZyBJSkcg\r
360
- --AaB03x--\r
361
- EOF
362
- req = Rack::Request.new Rack::MockRequest.env_for("/",
363
- "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
364
- "CONTENT_LENGTH" => input.size,
365
- :input => input)
366
-
367
- req.POST.should.include "fileupload"
368
- req.POST.should.include "reply"
369
-
370
- req.should.be.form_data
371
- req.content_length.should.equal input.size
372
- req.media_type.should.equal 'multipart/form-data'
373
- req.media_type_params.should.include 'boundary'
374
- req.media_type_params['boundary'].should.equal 'AaB03x'
375
-
376
- req.POST["reply"].should.equal "yes"
377
-
378
- f = req.POST["fileupload"]
379
- f.should.be.kind_of Hash
380
- f[:type].should.equal "image/jpeg"
381
- f[:filename].should.equal "dj.jpg"
382
- f.should.include :tempfile
383
- f[:tempfile].size.should.equal 76
384
- end
385
-
386
- specify "can parse big multipart form data" do
387
- input = <<EOF
388
- --AaB03x\r
389
- content-disposition: form-data; name="huge"; filename="huge"\r
390
- \r
391
- #{"x"*32768}\r
392
- --AaB03x\r
393
- content-disposition: form-data; name="mean"; filename="mean"\r
394
- \r
395
- --AaB03xha\r
396
- --AaB03x--\r
397
- EOF
398
- req = Rack::Request.new Rack::MockRequest.env_for("/",
399
- "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
400
- "CONTENT_LENGTH" => input.size,
401
- :input => input)
402
-
403
- req.POST["huge"][:tempfile].size.should.equal 32768
404
- req.POST["mean"][:tempfile].size.should.equal 10
405
- req.POST["mean"][:tempfile].read.should.equal "--AaB03xha"
406
- end
407
-
408
- specify "can detect invalid multipart form data" do
409
- input = <<EOF
410
- --AaB03x\r
411
- content-disposition: form-data; name="huge"; filename="huge"\r
412
- EOF
413
- req = Rack::Request.new Rack::MockRequest.env_for("/",
414
- "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
415
- "CONTENT_LENGTH" => input.size,
416
- :input => input)
417
-
418
- lambda { req.POST }.should.raise(EOFError)
419
-
420
- input = <<EOF
421
- --AaB03x\r
422
- content-disposition: form-data; name="huge"; filename="huge"\r
423
- \r
424
- foo\r
425
- EOF
426
- req = Rack::Request.new Rack::MockRequest.env_for("/",
427
- "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
428
- "CONTENT_LENGTH" => input.size,
429
- :input => input)
430
-
431
- lambda { req.POST }.should.raise(EOFError)
432
-
433
- input = <<EOF
434
- --AaB03x\r
435
- content-disposition: form-data; name="huge"; filename="huge"\r
436
- \r
437
- foo\r
438
- EOF
439
- req = Rack::Request.new Rack::MockRequest.env_for("/",
440
- "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
441
- "CONTENT_LENGTH" => input.size,
442
- :input => input)
443
-
444
- lambda { req.POST }.should.raise(EOFError)
445
- end
446
-
447
- specify "shouldn't try to interpret binary as utf8" do
448
- begin
449
- original_kcode = $KCODE
450
- $KCODE='UTF8'
451
-
452
- input = <<EOF
453
- --AaB03x\r
454
- content-disposition: form-data; name="fileupload"; filename="junk.a"\r
455
- content-type: application/octet-stream\r
456
- \r
457
- #{[0x36,0xCF,0x0A,0xF8].pack('c*')}\r
458
- --AaB03x--\r
459
- EOF
460
-
461
- req = Rack::Request.new Rack::MockRequest.env_for("/",
462
- "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
463
- "CONTENT_LENGTH" => input.size,
464
- :input => input)
465
-
466
- lambda{req.POST}.should.not.raise(EOFError)
467
- req.POST["fileupload"][:tempfile].size.should.equal 4
468
- ensure
469
- $KCODE = original_kcode
470
- end
471
- end
472
-
473
-
474
- specify "should work around buggy 1.8.* Tempfile equality" do
475
- input = <<EOF
476
- --AaB03x\r
477
- content-disposition: form-data; name="huge"; filename="huge"\r
478
- \r
479
- foo\r
480
- --AaB03x--
481
- EOF
482
-
483
- rack_input = Tempfile.new("rackspec")
484
- rack_input.write(input)
485
- rack_input.rewind
486
-
487
- req = Rack::Request.new Rack::MockRequest.env_for("/",
488
- "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
489
- "CONTENT_LENGTH" => input.size,
490
- :input => rack_input)
491
-
492
- lambda {req.POST}.should.not.raise
493
- lambda {req.POST}.should.blaming("input re-processed!").not.raise
494
- end
495
-
496
- specify "does conform to the Rack spec" do
497
- app = lambda { |env|
498
- content = Rack::Request.new(env).POST["file"].inspect
499
- size = content.respond_to?(:bytesize) ? content.bytesize : content.size
500
- [200, {"Content-Type" => "text/html", "Content-Length" => size.to_s}, [content]]
501
- }
502
-
503
- input = <<EOF
504
- --AaB03x\r
505
- content-disposition: form-data; name="reply"\r
506
- \r
507
- yes\r
508
- --AaB03x\r
509
- content-disposition: form-data; name="fileupload"; filename="dj.jpg"\r
510
- Content-Type: image/jpeg\r
511
- Content-Transfer-Encoding: base64\r
512
- \r
513
- /9j/4AAQSkZJRgABAQAAAQABAAD//gA+Q1JFQVRPUjogZ2QtanBlZyB2MS4wICh1c2luZyBJSkcg\r
514
- --AaB03x--\r
515
- EOF
516
- input.force_encoding("ASCII-8BIT") if input.respond_to? :force_encoding
517
- res = Rack::MockRequest.new(Rack::Lint.new(app)).get "/",
518
- "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
519
- "CONTENT_LENGTH" => input.size.to_s, "rack.input" => StringIO.new(input)
520
-
521
- res.should.be.ok
522
- end
523
-
524
- specify "should parse Accept-Encoding correctly" do
525
- parser = lambda do |x|
526
- Rack::Request.new(Rack::MockRequest.env_for("", "HTTP_ACCEPT_ENCODING" => x)).accept_encoding
527
- end
528
-
529
- parser.call(nil).should.equal([])
530
-
531
- parser.call("compress, gzip").should.equal([["compress", 1.0], ["gzip", 1.0]])
532
- parser.call("").should.equal([])
533
- parser.call("*").should.equal([["*", 1.0]])
534
- parser.call("compress;q=0.5, gzip;q=1.0").should.equal([["compress", 0.5], ["gzip", 1.0]])
535
- parser.call("gzip;q=1.0, identity; q=0.5, *;q=0").should.equal([["gzip", 1.0], ["identity", 0.5], ["*", 0] ])
536
-
537
- lambda { parser.call("gzip ; q=1.0") }.should.raise(RuntimeError)
538
- end
539
-
540
- specify 'should provide ip information' do
541
- app = lambda { |env|
542
- request = Rack::Request.new(env)
543
- response = Rack::Response.new
544
- response.write request.ip
545
- response.finish
546
- }
547
-
548
- mock = Rack::MockRequest.new(Rack::Lint.new(app))
549
- res = mock.get '/', 'REMOTE_ADDR' => '123.123.123.123'
550
- res.body.should.equal '123.123.123.123'
551
-
552
- res = mock.get '/',
553
- 'REMOTE_ADDR' => '123.123.123.123',
554
- 'HTTP_X_FORWARDED_FOR' => '234.234.234.234'
555
-
556
- res.body.should.equal '234.234.234.234'
557
-
558
- res = mock.get '/',
559
- 'REMOTE_ADDR' => '123.123.123.123',
560
- 'HTTP_X_FORWARDED_FOR' => '234.234.234.234,212.212.212.212'
561
-
562
- res.body.should.equal '212.212.212.212'
563
- end
564
-
565
- class MyRequest < Rack::Request
566
- def params
567
- {:foo => "bar"}
568
- end
569
- end
570
-
571
- specify "should allow subclass request to be instantiated after parent request" do
572
- env = Rack::MockRequest.env_for("/?foo=bar")
573
-
574
- req1 = Rack::Request.new(env)
575
- req1.GET.should.equal "foo" => "bar"
576
- req1.params.should.equal "foo" => "bar"
577
-
578
- req2 = MyRequest.new(env)
579
- req2.GET.should.equal "foo" => "bar"
580
- req2.params.should.equal :foo => "bar"
581
- end
582
-
583
- specify "should allow parent request to be instantiated after subclass request" do
584
- env = Rack::MockRequest.env_for("/?foo=bar")
585
-
586
- req1 = MyRequest.new(env)
587
- req1.GET.should.equal "foo" => "bar"
588
- req1.params.should.equal :foo => "bar"
589
-
590
- req2 = Rack::Request.new(env)
591
- req2.GET.should.equal "foo" => "bar"
592
- req2.params.should.equal "foo" => "bar"
593
- end
594
- end