actionpack 2.2.3 → 2.3.2

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

Potentially problematic release.


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

Files changed (264) hide show
  1. data/CHANGELOG +433 -375
  2. data/MIT-LICENSE +1 -1
  3. data/README +21 -75
  4. data/Rakefile +1 -1
  5. data/lib/action_controller.rb +80 -43
  6. data/lib/action_controller/assertions/model_assertions.rb +1 -0
  7. data/lib/action_controller/assertions/response_assertions.rb +43 -16
  8. data/lib/action_controller/assertions/routing_assertions.rb +1 -1
  9. data/lib/action_controller/assertions/selector_assertions.rb +17 -12
  10. data/lib/action_controller/assertions/tag_assertions.rb +1 -4
  11. data/lib/action_controller/base.rb +153 -82
  12. data/lib/action_controller/benchmarking.rb +9 -9
  13. data/lib/action_controller/caching.rb +9 -11
  14. data/lib/action_controller/caching/actions.rb +11 -18
  15. data/lib/action_controller/caching/fragments.rb +28 -20
  16. data/lib/action_controller/caching/pages.rb +13 -15
  17. data/lib/action_controller/caching/sweeping.rb +2 -2
  18. data/lib/action_controller/cgi_ext.rb +0 -1
  19. data/lib/action_controller/cgi_ext/cookie.rb +2 -0
  20. data/lib/action_controller/cgi_process.rb +54 -162
  21. data/lib/action_controller/cookies.rb +13 -25
  22. data/lib/action_controller/dispatcher.rb +43 -122
  23. data/lib/action_controller/failsafe.rb +52 -0
  24. data/lib/action_controller/flash.rb +38 -47
  25. data/lib/action_controller/helpers.rb +13 -9
  26. data/lib/action_controller/http_authentication.rb +203 -23
  27. data/lib/action_controller/integration.rb +126 -70
  28. data/lib/action_controller/layout.rb +36 -39
  29. data/lib/action_controller/middleware_stack.rb +119 -0
  30. data/lib/action_controller/middlewares.rb +13 -0
  31. data/lib/action_controller/mime_responds.rb +19 -4
  32. data/lib/action_controller/mime_type.rb +8 -0
  33. data/lib/action_controller/params_parser.rb +71 -0
  34. data/lib/action_controller/performance_test.rb +0 -1
  35. data/lib/action_controller/polymorphic_routes.rb +36 -30
  36. data/lib/action_controller/reloader.rb +14 -0
  37. data/lib/action_controller/request.rb +107 -499
  38. data/lib/action_controller/request_forgery_protection.rb +7 -39
  39. data/lib/action_controller/rescue.rb +55 -35
  40. data/lib/action_controller/resources.rb +34 -31
  41. data/lib/action_controller/response.rb +99 -57
  42. data/lib/action_controller/rewindable_input.rb +28 -0
  43. data/lib/action_controller/routing.rb +7 -7
  44. data/lib/action_controller/routing/builder.rb +4 -1
  45. data/lib/action_controller/routing/optimisations.rb +1 -1
  46. data/lib/action_controller/routing/recognition_optimisation.rb +1 -2
  47. data/lib/action_controller/routing/route.rb +15 -5
  48. data/lib/action_controller/routing/route_set.rb +82 -35
  49. data/lib/action_controller/routing/segments.rb +35 -0
  50. data/lib/action_controller/session/abstract_store.rb +181 -0
  51. data/lib/action_controller/session/cookie_store.rb +197 -175
  52. data/lib/action_controller/session/mem_cache_store.rb +36 -83
  53. data/lib/action_controller/session_management.rb +26 -134
  54. data/lib/action_controller/streaming.rb +24 -7
  55. data/lib/action_controller/templates/rescues/diagnostics.erb +2 -2
  56. data/lib/action_controller/templates/rescues/template_error.erb +2 -2
  57. data/lib/action_controller/test_case.rb +87 -30
  58. data/lib/action_controller/test_process.rb +145 -104
  59. data/lib/action_controller/uploaded_file.rb +44 -0
  60. data/lib/action_controller/url_rewriter.rb +3 -6
  61. data/lib/action_controller/vendor/html-scanner.rb +16 -0
  62. data/lib/action_controller/vendor/html-scanner/html/selector.rb +1 -1
  63. data/lib/action_controller/vendor/rack-1.0/rack.rb +89 -0
  64. data/lib/action_controller/vendor/rack-1.0/rack/adapter/camping.rb +22 -0
  65. data/lib/action_controller/vendor/rack-1.0/rack/auth/abstract/handler.rb +37 -0
  66. data/lib/action_controller/vendor/rack-1.0/rack/auth/abstract/request.rb +37 -0
  67. data/lib/action_controller/vendor/rack-1.0/rack/auth/basic.rb +58 -0
  68. data/lib/action_controller/vendor/rack-1.0/rack/auth/digest/md5.rb +124 -0
  69. data/lib/action_controller/vendor/rack-1.0/rack/auth/digest/nonce.rb +51 -0
  70. data/lib/action_controller/vendor/rack-1.0/rack/auth/digest/params.rb +55 -0
  71. data/lib/action_controller/vendor/rack-1.0/rack/auth/digest/request.rb +40 -0
  72. data/lib/action_controller/vendor/rack-1.0/rack/auth/openid.rb +480 -0
  73. data/lib/action_controller/vendor/rack-1.0/rack/builder.rb +63 -0
  74. data/lib/action_controller/vendor/rack-1.0/rack/cascade.rb +36 -0
  75. data/lib/action_controller/vendor/rack-1.0/rack/chunked.rb +49 -0
  76. data/lib/action_controller/vendor/rack-1.0/rack/commonlogger.rb +61 -0
  77. data/lib/action_controller/vendor/rack-1.0/rack/conditionalget.rb +45 -0
  78. data/lib/action_controller/vendor/rack-1.0/rack/content_length.rb +29 -0
  79. data/lib/action_controller/vendor/rack-1.0/rack/content_type.rb +23 -0
  80. data/lib/action_controller/vendor/rack-1.0/rack/deflater.rb +85 -0
  81. data/lib/action_controller/vendor/rack-1.0/rack/directory.rb +153 -0
  82. data/lib/action_controller/vendor/rack-1.0/rack/file.rb +88 -0
  83. data/lib/action_controller/vendor/rack-1.0/rack/handler.rb +48 -0
  84. data/lib/action_controller/vendor/rack-1.0/rack/handler/cgi.rb +61 -0
  85. data/lib/action_controller/vendor/rack-1.0/rack/handler/evented_mongrel.rb +8 -0
  86. data/lib/action_controller/vendor/rack-1.0/rack/handler/fastcgi.rb +89 -0
  87. data/lib/action_controller/vendor/rack-1.0/rack/handler/lsws.rb +55 -0
  88. data/lib/action_controller/vendor/rack-1.0/rack/handler/mongrel.rb +84 -0
  89. data/lib/action_controller/vendor/rack-1.0/rack/handler/scgi.rb +59 -0
  90. data/lib/action_controller/vendor/rack-1.0/rack/handler/swiftiplied_mongrel.rb +8 -0
  91. data/lib/action_controller/vendor/rack-1.0/rack/handler/thin.rb +18 -0
  92. data/lib/action_controller/vendor/rack-1.0/rack/handler/webrick.rb +67 -0
  93. data/lib/action_controller/vendor/rack-1.0/rack/head.rb +19 -0
  94. data/lib/action_controller/vendor/rack-1.0/rack/lint.rb +462 -0
  95. data/lib/action_controller/vendor/rack-1.0/rack/lobster.rb +65 -0
  96. data/lib/action_controller/vendor/rack-1.0/rack/lock.rb +16 -0
  97. data/lib/action_controller/vendor/rack-1.0/rack/methodoverride.rb +27 -0
  98. data/lib/action_controller/vendor/rack-1.0/rack/mime.rb +204 -0
  99. data/lib/action_controller/vendor/rack-1.0/rack/mock.rb +160 -0
  100. data/lib/action_controller/vendor/rack-1.0/rack/recursive.rb +57 -0
  101. data/lib/action_controller/vendor/rack-1.0/rack/reloader.rb +64 -0
  102. data/lib/action_controller/vendor/rack-1.0/rack/request.rb +241 -0
  103. data/lib/action_controller/vendor/rack-1.0/rack/response.rb +179 -0
  104. data/lib/action_controller/vendor/rack-1.0/rack/session/abstract/id.rb +142 -0
  105. data/lib/action_controller/vendor/rack-1.0/rack/session/cookie.rb +91 -0
  106. data/lib/action_controller/vendor/rack-1.0/rack/session/memcache.rb +109 -0
  107. data/lib/action_controller/vendor/rack-1.0/rack/session/pool.rb +100 -0
  108. data/lib/action_controller/vendor/rack-1.0/rack/showexceptions.rb +349 -0
  109. data/lib/action_controller/vendor/rack-1.0/rack/showstatus.rb +106 -0
  110. data/lib/action_controller/vendor/rack-1.0/rack/static.rb +38 -0
  111. data/lib/action_controller/vendor/rack-1.0/rack/urlmap.rb +55 -0
  112. data/lib/action_controller/vendor/rack-1.0/rack/utils.rb +392 -0
  113. data/lib/action_controller/verification.rb +1 -1
  114. data/lib/action_pack.rb +1 -1
  115. data/lib/action_pack/version.rb +2 -2
  116. data/lib/action_view.rb +22 -17
  117. data/lib/action_view/base.rb +53 -79
  118. data/lib/action_view/erb/util.rb +38 -0
  119. data/lib/action_view/helpers.rb +24 -5
  120. data/lib/action_view/helpers/active_record_helper.rb +2 -2
  121. data/lib/action_view/helpers/asset_tag_helper.rb +81 -50
  122. data/lib/action_view/helpers/atom_feed_helper.rb +1 -1
  123. data/lib/action_view/helpers/benchmark_helper.rb +26 -5
  124. data/lib/action_view/helpers/date_helper.rb +82 -7
  125. data/lib/action_view/helpers/form_helper.rb +295 -64
  126. data/lib/action_view/helpers/form_options_helper.rb +160 -18
  127. data/lib/action_view/helpers/form_tag_helper.rb +2 -2
  128. data/lib/action_view/helpers/number_helper.rb +31 -18
  129. data/lib/action_view/helpers/prototype_helper.rb +2 -12
  130. data/lib/action_view/helpers/sanitize_helper.rb +0 -10
  131. data/lib/action_view/helpers/scriptaculous_helper.rb +1 -0
  132. data/lib/action_view/helpers/tag_helper.rb +3 -4
  133. data/lib/action_view/helpers/text_helper.rb +99 -122
  134. data/lib/action_view/helpers/translation_helper.rb +19 -1
  135. data/lib/action_view/helpers/url_helper.rb +25 -2
  136. data/lib/action_view/inline_template.rb +1 -1
  137. data/lib/action_view/locale/en.yml +19 -1
  138. data/lib/action_view/partials.rb +46 -9
  139. data/lib/action_view/paths.rb +28 -84
  140. data/lib/action_view/reloadable_template.rb +117 -0
  141. data/lib/action_view/renderable.rb +28 -35
  142. data/lib/action_view/renderable_partial.rb +3 -4
  143. data/lib/action_view/template.rb +172 -31
  144. data/lib/action_view/template_error.rb +8 -9
  145. data/lib/action_view/template_handler.rb +1 -1
  146. data/lib/action_view/template_handlers.rb +9 -6
  147. data/lib/action_view/template_handlers/erb.rb +2 -39
  148. data/lib/action_view/template_handlers/rjs.rb +1 -0
  149. data/lib/action_view/test_case.rb +27 -1
  150. data/test/abstract_unit.rb +23 -17
  151. data/test/active_record_unit.rb +5 -4
  152. data/test/activerecord/active_record_store_test.rb +139 -106
  153. data/test/activerecord/render_partial_with_record_identification_test.rb +5 -21
  154. data/test/controller/action_pack_assertions_test.rb +25 -23
  155. data/test/controller/addresses_render_test.rb +3 -6
  156. data/test/controller/assert_select_test.rb +83 -70
  157. data/test/controller/base_test.rb +11 -13
  158. data/test/controller/benchmark_test.rb +3 -3
  159. data/test/controller/caching_test.rb +34 -24
  160. data/test/controller/capture_test.rb +3 -6
  161. data/test/controller/content_type_test.rb +3 -6
  162. data/test/controller/cookie_test.rb +31 -66
  163. data/test/controller/deprecation/deprecated_base_methods_test.rb +9 -11
  164. data/test/controller/dispatcher_test.rb +23 -28
  165. data/test/controller/fake_models.rb +8 -0
  166. data/test/controller/filters_test.rb +6 -2
  167. data/test/controller/flash_test.rb +2 -6
  168. data/test/controller/helper_test.rb +15 -1
  169. data/test/controller/html-scanner/document_test.rb +1 -1
  170. data/test/controller/html-scanner/sanitizer_test.rb +1 -1
  171. data/test/controller/http_basic_authentication_test.rb +88 -0
  172. data/test/controller/http_digest_authentication_test.rb +178 -0
  173. data/test/controller/integration_test.rb +56 -52
  174. data/test/controller/layout_test.rb +46 -44
  175. data/test/controller/middleware_stack_test.rb +90 -0
  176. data/test/controller/mime_responds_test.rb +7 -11
  177. data/test/controller/mime_type_test.rb +9 -0
  178. data/test/controller/polymorphic_routes_test.rb +235 -151
  179. data/test/controller/rack_test.rb +52 -81
  180. data/test/controller/redirect_test.rb +6 -14
  181. data/test/controller/render_test.rb +273 -60
  182. data/test/controller/request/json_params_parsing_test.rb +45 -0
  183. data/test/controller/request/multipart_params_parsing_test.rb +223 -0
  184. data/test/controller/request/query_string_parsing_test.rb +120 -0
  185. data/test/controller/request/url_encoded_params_parsing_test.rb +184 -0
  186. data/test/controller/request/xml_params_parsing_test.rb +88 -0
  187. data/test/controller/request_forgery_protection_test.rb +17 -98
  188. data/test/controller/request_test.rb +45 -530
  189. data/test/controller/rescue_test.rb +45 -22
  190. data/test/controller/resources_test.rb +112 -37
  191. data/test/controller/routing_test.rb +1442 -1384
  192. data/test/controller/selector_test.rb +3 -3
  193. data/test/controller/send_file_test.rb +30 -3
  194. data/test/controller/session/cookie_store_test.rb +169 -240
  195. data/test/controller/session/mem_cache_store_test.rb +94 -148
  196. data/test/controller/session/test_session_test.rb +58 -0
  197. data/test/controller/test_test.rb +32 -13
  198. data/test/controller/url_rewriter_test.rb +54 -4
  199. data/test/controller/verification_test.rb +1 -1
  200. data/test/controller/view_paths_test.rb +15 -15
  201. data/test/controller/webservice_test.rb +178 -147
  202. data/test/fixtures/alternate_helpers/foo_helper.rb +3 -0
  203. data/test/fixtures/layout_tests/alt/layouts/alt.rhtml +0 -0
  204. data/test/fixtures/layouts/default_html.html.erb +1 -0
  205. data/test/fixtures/layouts/xhr.html.erb +2 -0
  206. data/test/fixtures/multipart/empty +10 -0
  207. data/test/fixtures/multipart/hello.txt +1 -0
  208. data/test/fixtures/multipart/none +9 -0
  209. data/test/fixtures/public/500.da.html +1 -0
  210. data/test/fixtures/quiz/questions/_question.html.erb +1 -0
  211. data/test/fixtures/replies.yml +1 -1
  212. data/test/fixtures/test/_one.html.erb +1 -0
  213. data/test/fixtures/test/_two.html.erb +1 -0
  214. data/test/fixtures/test/dont_pick_me +1 -0
  215. data/test/fixtures/test/hello.builder +1 -1
  216. data/test/fixtures/test/hello_world.da.html.erb +1 -0
  217. data/test/fixtures/test/hello_world.erb~ +1 -0
  218. data/test/fixtures/test/hello_world.pt-BR.html.erb +1 -0
  219. data/test/fixtures/test/malformed/malformed.en.html.erb~ +1 -0
  220. data/test/fixtures/test/malformed/malformed.erb~ +1 -0
  221. data/test/fixtures/test/malformed/malformed.html.erb~ +1 -0
  222. data/test/fixtures/test/render_explicit_html_template.js.rjs +1 -0
  223. data/test/fixtures/test/render_implicit_html_template.js.rjs +1 -0
  224. data/test/fixtures/test/render_implicit_html_template_from_xhr_request.da.html.erb +1 -0
  225. data/test/fixtures/test/render_implicit_html_template_from_xhr_request.html.erb +1 -0
  226. data/test/fixtures/test/render_implicit_js_template_without_layout.js.erb +1 -0
  227. data/test/fixtures/test/utf8.html.erb +2 -0
  228. data/test/template/active_record_helper_i18n_test.rb +31 -33
  229. data/test/template/active_record_helper_test.rb +34 -0
  230. data/test/template/asset_tag_helper_test.rb +52 -14
  231. data/test/template/atom_feed_helper_test.rb +3 -5
  232. data/test/template/benchmark_helper_test.rb +50 -24
  233. data/test/template/compiled_templates_test.rb +177 -33
  234. data/test/template/date_helper_i18n_test.rb +88 -81
  235. data/test/template/date_helper_test.rb +427 -43
  236. data/test/template/form_helper_test.rb +243 -44
  237. data/test/template/form_options_helper_test.rb +631 -565
  238. data/test/template/form_tag_helper_test.rb +9 -2
  239. data/test/template/javascript_helper_test.rb +0 -5
  240. data/test/template/number_helper_i18n_test.rb +60 -48
  241. data/test/template/number_helper_test.rb +1 -0
  242. data/test/template/render_test.rb +117 -35
  243. data/test/template/test_test.rb +4 -6
  244. data/test/template/text_helper_test.rb +129 -50
  245. data/test/template/translation_helper_test.rb +23 -19
  246. data/test/template/url_helper_test.rb +35 -2
  247. data/test/view/test_case_test.rb +8 -0
  248. metadata +197 -23
  249. data/lib/action_controller/assertions.rb +0 -69
  250. data/lib/action_controller/caching/sql_cache.rb +0 -18
  251. data/lib/action_controller/cgi_ext/session.rb +0 -53
  252. data/lib/action_controller/components.rb +0 -169
  253. data/lib/action_controller/rack_process.rb +0 -297
  254. data/lib/action_controller/request_profiler.rb +0 -169
  255. data/lib/action_controller/session/active_record_store.rb +0 -340
  256. data/lib/action_controller/session/drb_server.rb +0 -32
  257. data/lib/action_controller/session/drb_store.rb +0 -35
  258. data/test/controller/cgi_test.rb +0 -269
  259. data/test/controller/components_test.rb +0 -156
  260. data/test/controller/http_authentication_test.rb +0 -54
  261. data/test/controller/integration_upload_test.rb +0 -43
  262. data/test/controller/session_fixation_test.rb +0 -89
  263. data/test/controller/session_management_test.rb +0 -178
  264. data/test/fixtures/test/hello_world.js +0 -1
@@ -0,0 +1,45 @@
1
+ require 'abstract_unit'
2
+
3
+ class JsonParamsParsingTest < ActionController::IntegrationTest
4
+ class TestController < ActionController::Base
5
+ class << self
6
+ attr_accessor :last_request_parameters
7
+ end
8
+
9
+ def parse
10
+ self.class.last_request_parameters = request.request_parameters
11
+ head :ok
12
+ end
13
+ end
14
+
15
+ def teardown
16
+ TestController.last_request_parameters = nil
17
+ end
18
+
19
+ test "parses json params for application json" do
20
+ assert_parses(
21
+ {"person" => {"name" => "David"}},
22
+ "{\"person\": {\"name\": \"David\"}}", { 'CONTENT_TYPE' => 'application/json' }
23
+ )
24
+ end
25
+
26
+ test "parses json params for application jsonrequest" do
27
+ assert_parses(
28
+ {"person" => {"name" => "David"}},
29
+ "{\"person\": {\"name\": \"David\"}}", { 'CONTENT_TYPE' => 'application/jsonrequest' }
30
+ )
31
+ end
32
+
33
+ private
34
+ def assert_parses(expected, actual, headers = {})
35
+ with_routing do |set|
36
+ set.draw do |map|
37
+ map.connect ':action', :controller => "json_params_parsing_test/test"
38
+ end
39
+
40
+ post "/parse", actual, headers
41
+ assert_response :ok
42
+ assert_equal(expected, TestController.last_request_parameters)
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,223 @@
1
+ require 'abstract_unit'
2
+
3
+ class MultipartParamsParsingTest < ActionController::IntegrationTest
4
+ class TestController < ActionController::Base
5
+ class << self
6
+ attr_accessor :last_request_parameters
7
+ end
8
+
9
+ def parse
10
+ self.class.last_request_parameters = request.request_parameters
11
+ head :ok
12
+ end
13
+
14
+ def read
15
+ render :text => "File: #{params[:uploaded_data].read}"
16
+ end
17
+ end
18
+
19
+ FIXTURE_PATH = File.dirname(__FILE__) + '/../../fixtures/multipart'
20
+
21
+ def teardown
22
+ TestController.last_request_parameters = nil
23
+ end
24
+
25
+ test "parses single parameter" do
26
+ assert_equal({ 'foo' => 'bar' }, parse_multipart('single_parameter'))
27
+ end
28
+
29
+ test "parses bracketed parameters" do
30
+ assert_equal({ 'foo' => { 'baz' => 'bar'}}, parse_multipart('bracketed_param'))
31
+ end
32
+
33
+ test "parses text file" do
34
+ params = parse_multipart('text_file')
35
+ assert_equal %w(file foo), params.keys.sort
36
+ assert_equal 'bar', params['foo']
37
+
38
+ file = params['file']
39
+ assert_kind_of Tempfile, file
40
+ assert_equal 'file.txt', file.original_filename
41
+ assert_equal "text/plain", file.content_type
42
+ assert_equal 'contents', file.read
43
+ end
44
+
45
+ test "parses boundary problem file" do
46
+ params = parse_multipart('boundary_problem_file')
47
+ assert_equal %w(file foo), params.keys.sort
48
+
49
+ file = params['file']
50
+ foo = params['foo']
51
+
52
+ assert_kind_of Tempfile, file
53
+
54
+ assert_equal 'file.txt', file.original_filename
55
+ assert_equal "text/plain", file.content_type
56
+
57
+ assert_equal 'bar', foo
58
+ end
59
+
60
+ test "parses large text file" do
61
+ params = parse_multipart('large_text_file')
62
+ assert_equal %w(file foo), params.keys.sort
63
+ assert_equal 'bar', params['foo']
64
+
65
+ file = params['file']
66
+
67
+ assert_kind_of Tempfile, file
68
+
69
+ assert_equal 'file.txt', file.original_filename
70
+ assert_equal "text/plain", file.content_type
71
+ assert ('a' * 20480) == file.read
72
+ end
73
+
74
+ test "parses binary file" do
75
+ params = parse_multipart('binary_file')
76
+ assert_equal %w(file flowers foo), params.keys.sort
77
+ assert_equal 'bar', params['foo']
78
+
79
+ file = params['file']
80
+ assert_kind_of Tempfile, file
81
+ assert_equal 'file.csv', file.original_filename
82
+ assert_nil file.content_type
83
+ assert_equal 'contents', file.read
84
+
85
+ file = params['flowers']
86
+ assert_kind_of Tempfile, file
87
+ assert_equal 'flowers.jpg', file.original_filename
88
+ assert_equal "image/jpeg", file.content_type
89
+ assert_equal 19512, file.size
90
+ end
91
+
92
+ test "parses mixed files" do
93
+ params = parse_multipart('mixed_files')
94
+ assert_equal %w(files foo), params.keys.sort
95
+ assert_equal 'bar', params['foo']
96
+
97
+ # Ruby CGI doesn't handle multipart/mixed for us.
98
+ files = params['files']
99
+ assert_kind_of String, files
100
+ files.force_encoding('ASCII-8BIT') if files.respond_to?(:force_encoding)
101
+ assert_equal 19756, files.size
102
+ end
103
+
104
+ test "does not create tempfile if no file has been selected" do
105
+ params = parse_multipart('none')
106
+ assert_equal %w(submit-name), params.keys.sort
107
+ assert_equal 'Larry', params['submit-name']
108
+ assert_equal nil, params['files']
109
+ end
110
+
111
+ test "parses empty upload file" do
112
+ params = parse_multipart('empty')
113
+ assert_equal %w(files submit-name), params.keys.sort
114
+ assert_equal 'Larry', params['submit-name']
115
+ assert params['files']
116
+ assert_equal "", params['files'].read
117
+ end
118
+
119
+ test "uploads and reads binary file" do
120
+ with_test_routing do
121
+ fixture = FIXTURE_PATH + "/mona_lisa.jpg"
122
+ params = { :uploaded_data => fixture_file_upload(fixture, "image/jpg") }
123
+ post '/read', params
124
+ expected_length = 'File: '.length + File.size(fixture)
125
+ assert_equal expected_length, response.content_length
126
+ end
127
+ end
128
+
129
+ test "uploads and reads file" do
130
+ with_test_routing do
131
+ post '/read', :uploaded_data => fixture_file_upload(FIXTURE_PATH + "/hello.txt", "text/plain")
132
+ assert_equal "File: Hello", response.body
133
+ end
134
+ end
135
+
136
+ # The lint wrapper is used in integration tests
137
+ # instead of a normal StringIO class
138
+ InputWrapper = Rack::Lint::InputWrapper
139
+
140
+ test "parses unwindable stream" do
141
+ InputWrapper.any_instance.stubs(:rewind).raises(Errno::ESPIPE)
142
+ params = parse_multipart('large_text_file')
143
+ assert_equal %w(file foo), params.keys.sort
144
+ assert_equal 'bar', params['foo']
145
+ end
146
+
147
+ test "uploads and reads file with unwindable input" do
148
+ InputWrapper.any_instance.stubs(:rewind).raises(Errno::ESPIPE)
149
+
150
+ with_test_routing do
151
+ post '/read', :uploaded_data => fixture_file_upload(FIXTURE_PATH + "/hello.txt", "text/plain")
152
+ assert_equal "File: Hello", response.body
153
+ end
154
+ end
155
+
156
+ test "passes through rack middleware and uploads file" do
157
+ with_muck_middleware do
158
+ with_test_routing do
159
+ post '/read', :uploaded_data => fixture_file_upload(FIXTURE_PATH + "/hello.txt", "text/plain")
160
+ assert_equal "File: Hello", response.body
161
+ end
162
+ end
163
+ end
164
+
165
+ test "passes through rack middleware and uploads file with unwindable input" do
166
+ InputWrapper.any_instance.stubs(:rewind).raises(Errno::ESPIPE)
167
+
168
+ with_muck_middleware do
169
+ with_test_routing do
170
+ post '/read', :uploaded_data => fixture_file_upload(FIXTURE_PATH + "/hello.txt", "text/plain")
171
+ assert_equal "File: Hello", response.body
172
+ end
173
+ end
174
+ end
175
+
176
+ private
177
+ def fixture(name)
178
+ File.open(File.join(FIXTURE_PATH, name), 'rb') do |file|
179
+ { "rack.input" => file.read,
180
+ "CONTENT_TYPE" => "multipart/form-data; boundary=AaB03x",
181
+ "CONTENT_LENGTH" => file.stat.size.to_s }
182
+ end
183
+ end
184
+
185
+ def parse_multipart(name)
186
+ with_test_routing do
187
+ headers = fixture(name)
188
+ post "/parse", headers.delete("rack.input"), headers
189
+ assert_response :ok
190
+ TestController.last_request_parameters
191
+ end
192
+ end
193
+
194
+ def with_test_routing
195
+ with_routing do |set|
196
+ set.draw do |map|
197
+ map.connect ':action', :controller => "multipart_params_parsing_test/test"
198
+ end
199
+ yield
200
+ end
201
+ end
202
+
203
+ class MuckMiddleware
204
+ def initialize(app)
205
+ @app = app
206
+ end
207
+
208
+ def call(env)
209
+ req = Rack::Request.new(env)
210
+ req.params # Parse params
211
+ @app.call(env)
212
+ end
213
+ end
214
+
215
+ def with_muck_middleware
216
+ original_middleware = ActionController::Dispatcher.middleware
217
+ middleware = original_middleware.dup
218
+ middleware.insert_after ActionController::RewindableInput, MuckMiddleware
219
+ ActionController::Dispatcher.middleware = middleware
220
+ yield
221
+ ActionController::Dispatcher.middleware = original_middleware
222
+ end
223
+ end
@@ -0,0 +1,120 @@
1
+ require 'abstract_unit'
2
+
3
+ class QueryStringParsingTest < ActionController::IntegrationTest
4
+ class TestController < ActionController::Base
5
+ class << self
6
+ attr_accessor :last_query_parameters
7
+ end
8
+
9
+ def parse
10
+ self.class.last_query_parameters = request.query_parameters
11
+ head :ok
12
+ end
13
+ end
14
+
15
+ def teardown
16
+ TestController.last_query_parameters = nil
17
+ end
18
+
19
+ test "query string" do
20
+ assert_parses(
21
+ {"action" => "create_customer", "full_name" => "David Heinemeier Hansson", "customerId" => "1"},
22
+ "action=create_customer&full_name=David%20Heinemeier%20Hansson&customerId=1"
23
+ )
24
+ end
25
+
26
+ test "deep query string" do
27
+ assert_parses(
28
+ {'x' => {'y' => {'z' => '10'}}},
29
+ "x[y][z]=10"
30
+ )
31
+ end
32
+
33
+ test "deep query string with array" do
34
+ assert_parses({'x' => {'y' => {'z' => ['10']}}}, 'x[y][z][]=10')
35
+ assert_parses({'x' => {'y' => {'z' => ['10', '5']}}}, 'x[y][z][]=10&x[y][z][]=5')
36
+ end
37
+
38
+ test "deep query string with array of hash" do
39
+ assert_parses({'x' => {'y' => [{'z' => '10'}]}}, 'x[y][][z]=10')
40
+ assert_parses({'x' => {'y' => [{'z' => '10', 'w' => '10'}]}}, 'x[y][][z]=10&x[y][][w]=10')
41
+ assert_parses({'x' => {'y' => [{'z' => '10', 'v' => {'w' => '10'}}]}}, 'x[y][][z]=10&x[y][][v][w]=10')
42
+ end
43
+
44
+ test "deep query string with array of hashes with one pair" do
45
+ assert_parses({'x' => {'y' => [{'z' => '10'}, {'z' => '20'}]}}, 'x[y][][z]=10&x[y][][z]=20')
46
+ end
47
+
48
+ test "deep query string with array of hashes with multiple pairs" do
49
+ assert_parses(
50
+ {'x' => {'y' => [{'z' => '10', 'w' => 'a'}, {'z' => '20', 'w' => 'b'}]}},
51
+ 'x[y][][z]=10&x[y][][w]=a&x[y][][z]=20&x[y][][w]=b'
52
+ )
53
+ end
54
+
55
+ test "query string with nil" do
56
+ assert_parses(
57
+ { "action" => "create_customer", "full_name" => ''},
58
+ "action=create_customer&full_name="
59
+ )
60
+ end
61
+
62
+ test "query string with array" do
63
+ assert_parses(
64
+ { "action" => "create_customer", "selected" => ["1", "2", "3"]},
65
+ "action=create_customer&selected[]=1&selected[]=2&selected[]=3"
66
+ )
67
+ end
68
+
69
+ test "query string with amps" do
70
+ assert_parses(
71
+ { "action" => "create_customer", "name" => "Don't & Does"},
72
+ "action=create_customer&name=Don%27t+%26+Does"
73
+ )
74
+ end
75
+
76
+ test "query string with many equal" do
77
+ assert_parses(
78
+ { "action" => "create_customer", "full_name" => "abc=def=ghi"},
79
+ "action=create_customer&full_name=abc=def=ghi"
80
+ )
81
+ end
82
+
83
+ test "query string without equal" do
84
+ assert_parses({ "action" => nil }, "action")
85
+ end
86
+
87
+ test "query string with empty key" do
88
+ assert_parses(
89
+ { "action" => "create_customer", "full_name" => "David Heinemeier Hansson" },
90
+ "action=create_customer&full_name=David%20Heinemeier%20Hansson&=Save"
91
+ )
92
+ end
93
+
94
+ test "query string with many ampersands" do
95
+ assert_parses(
96
+ { "action" => "create_customer", "full_name" => "David Heinemeier Hansson"},
97
+ "&action=create_customer&&&full_name=David%20Heinemeier%20Hansson"
98
+ )
99
+ end
100
+
101
+ test "unbalanced query string with array" do
102
+ assert_parses(
103
+ {'location' => ["1", "2"], 'age_group' => ["2"]},
104
+ "location[]=1&location[]=2&age_group[]=2"
105
+ )
106
+ end
107
+
108
+ private
109
+ def assert_parses(expected, actual)
110
+ with_routing do |set|
111
+ set.draw do |map|
112
+ map.connect ':action', :controller => "query_string_parsing_test/test"
113
+ end
114
+
115
+ get "/parse", actual
116
+ assert_response :ok
117
+ assert_equal(expected, TestController.last_query_parameters)
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,184 @@
1
+ require 'abstract_unit'
2
+
3
+ class UrlEncodedParamsParsingTest < ActionController::IntegrationTest
4
+ class TestController < ActionController::Base
5
+ class << self
6
+ attr_accessor :last_request_parameters, :last_request_type
7
+ end
8
+
9
+ def parse
10
+ self.class.last_request_parameters = request.request_parameters
11
+ head :ok
12
+ end
13
+ end
14
+
15
+ def teardown
16
+ TestController.last_request_parameters = nil
17
+ end
18
+
19
+ test "parses unbalanced query string with array" do
20
+ assert_parses(
21
+ {'location' => ["1", "2"], 'age_group' => ["2"]},
22
+ "location[]=1&location[]=2&age_group[]=2"
23
+ )
24
+ end
25
+
26
+ test "parses nested hash" do
27
+ query = [
28
+ "note[viewers][viewer][][type]=User",
29
+ "note[viewers][viewer][][id]=1",
30
+ "note[viewers][viewer][][type]=Group",
31
+ "note[viewers][viewer][][id]=2"
32
+ ].join("&")
33
+
34
+ expected = { "note" => { "viewers"=>{"viewer"=>[{ "id"=>"1", "type"=>"User"}, {"type"=>"Group", "id"=>"2"} ]} } }
35
+ assert_parses(expected, query)
36
+ end
37
+
38
+ test "parses more complex nesting" do
39
+ query = [
40
+ "customers[boston][first][name]=David",
41
+ "customers[boston][first][url]=http://David",
42
+ "customers[boston][second][name]=Allan",
43
+ "customers[boston][second][url]=http://Allan",
44
+ "something_else=blah",
45
+ "something_nil=",
46
+ "something_empty=",
47
+ "products[first]=Apple Computer",
48
+ "products[second]=Pc",
49
+ "=Save"
50
+ ].join("&")
51
+
52
+ expected = {
53
+ "customers" => {
54
+ "boston" => {
55
+ "first" => {
56
+ "name" => "David",
57
+ "url" => "http://David"
58
+ },
59
+ "second" => {
60
+ "name" => "Allan",
61
+ "url" => "http://Allan"
62
+ }
63
+ }
64
+ },
65
+ "something_else" => "blah",
66
+ "something_empty" => "",
67
+ "something_nil" => "",
68
+ "products" => {
69
+ "first" => "Apple Computer",
70
+ "second" => "Pc"
71
+ }
72
+ }
73
+
74
+ assert_parses expected, query
75
+ end
76
+
77
+ test "parses params with array" do
78
+ query = "selected[]=1&selected[]=2&selected[]=3"
79
+ expected = { "selected" => [ "1", "2", "3" ] }
80
+ assert_parses expected, query
81
+ end
82
+
83
+ test "parses params with nil key" do
84
+ query = "=&test2=value1"
85
+ expected = { "test2" => "value1" }
86
+ assert_parses expected, query
87
+ end
88
+
89
+ test "parses params with array prefix and hashes" do
90
+ query = "a[][b][c]=d"
91
+ expected = {"a" => [{"b" => {"c" => "d"}}]}
92
+ assert_parses expected, query
93
+ end
94
+
95
+ test "parses params with complex nesting" do
96
+ query = "a[][b][c][][d][]=e"
97
+ expected = {"a" => [{"b" => {"c" => [{"d" => ["e"]}]}}]}
98
+ assert_parses expected, query
99
+ end
100
+
101
+ test "parses params with file path" do
102
+ query = [
103
+ "customers[boston][first][name]=David",
104
+ "something_else=blah",
105
+ "logo=#{File.expand_path(__FILE__)}"
106
+ ].join("&")
107
+
108
+ expected = {
109
+ "customers" => {
110
+ "boston" => {
111
+ "first" => {
112
+ "name" => "David"
113
+ }
114
+ }
115
+ },
116
+ "something_else" => "blah",
117
+ "logo" => File.expand_path(__FILE__),
118
+ }
119
+
120
+ assert_parses expected, query
121
+ end
122
+
123
+ test "parses params with Safari 2 trailing null character" do
124
+ query = "selected[]=1&selected[]=2&selected[]=3\0"
125
+ expected = { "selected" => [ "1", "2", "3" ] }
126
+ assert_parses expected, query
127
+ end
128
+
129
+ test "passes through rack middleware and parses params" do
130
+ with_muck_middleware do
131
+ assert_parses({ "a" => { "b" => "c" } }, "a[b]=c")
132
+ end
133
+ end
134
+
135
+ # The lint wrapper is used in integration tests
136
+ # instead of a normal StringIO class
137
+ InputWrapper = Rack::Lint::InputWrapper
138
+
139
+ test "passes through rack middleware and parses params with unwindable input" do
140
+ InputWrapper.any_instance.stubs(:rewind).raises(Errno::ESPIPE)
141
+ with_muck_middleware do
142
+ assert_parses({ "a" => { "b" => "c" } }, "a[b]=c")
143
+ end
144
+ end
145
+
146
+ private
147
+ class MuckMiddleware
148
+ def initialize(app)
149
+ @app = app
150
+ end
151
+
152
+ def call(env)
153
+ req = Rack::Request.new(env)
154
+ req.params # Parse params
155
+ @app.call(env)
156
+ end
157
+ end
158
+
159
+ def with_muck_middleware
160
+ original_middleware = ActionController::Dispatcher.middleware
161
+ middleware = original_middleware.dup
162
+ middleware.insert_after ActionController::RewindableInput, MuckMiddleware
163
+ ActionController::Dispatcher.middleware = middleware
164
+ yield
165
+ ActionController::Dispatcher.middleware = original_middleware
166
+ end
167
+
168
+ def with_test_routing
169
+ with_routing do |set|
170
+ set.draw do |map|
171
+ map.connect ':action', :controller => "url_encoded_params_parsing_test/test"
172
+ end
173
+ yield
174
+ end
175
+ end
176
+
177
+ def assert_parses(expected, actual)
178
+ with_test_routing do
179
+ post "/parse", actual
180
+ assert_response :ok
181
+ assert_equal(expected, TestController.last_request_parameters)
182
+ end
183
+ end
184
+ end