actionpack 3.2.19 → 4.0.0

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 (263) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +850 -401
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +5 -288
  5. data/lib/abstract_controller/asset_paths.rb +2 -2
  6. data/lib/abstract_controller/base.rb +39 -37
  7. data/lib/abstract_controller/callbacks.rb +101 -82
  8. data/lib/abstract_controller/collector.rb +7 -3
  9. data/lib/abstract_controller/helpers.rb +25 -13
  10. data/lib/abstract_controller/layouts.rb +74 -74
  11. data/lib/abstract_controller/logger.rb +1 -2
  12. data/lib/abstract_controller/rendering.rb +30 -13
  13. data/lib/abstract_controller/translation.rb +16 -1
  14. data/lib/abstract_controller/url_for.rb +6 -6
  15. data/lib/abstract_controller/view_paths.rb +1 -1
  16. data/lib/abstract_controller.rb +1 -8
  17. data/lib/action_controller/base.rb +46 -22
  18. data/lib/action_controller/caching/fragments.rb +23 -53
  19. data/lib/action_controller/caching.rb +46 -33
  20. data/lib/action_controller/deprecated/integration_test.rb +3 -0
  21. data/lib/action_controller/deprecated.rb +5 -1
  22. data/lib/action_controller/log_subscriber.rb +16 -8
  23. data/lib/action_controller/metal/conditional_get.rb +76 -32
  24. data/lib/action_controller/metal/data_streaming.rb +20 -26
  25. data/lib/action_controller/metal/exceptions.rb +19 -6
  26. data/lib/action_controller/metal/flash.rb +24 -9
  27. data/lib/action_controller/metal/force_ssl.rb +70 -12
  28. data/lib/action_controller/metal/head.rb +25 -4
  29. data/lib/action_controller/metal/helpers.rb +5 -9
  30. data/lib/action_controller/metal/hide_actions.rb +0 -1
  31. data/lib/action_controller/metal/http_authentication.rb +107 -83
  32. data/lib/action_controller/metal/implicit_render.rb +1 -1
  33. data/lib/action_controller/metal/instrumentation.rb +2 -1
  34. data/lib/action_controller/metal/live.rb +175 -0
  35. data/lib/action_controller/metal/mime_responds.rb +161 -47
  36. data/lib/action_controller/metal/params_wrapper.rb +112 -74
  37. data/lib/action_controller/metal/rack_delegation.rb +9 -3
  38. data/lib/action_controller/metal/redirecting.rb +15 -20
  39. data/lib/action_controller/metal/renderers.rb +11 -9
  40. data/lib/action_controller/metal/rendering.rb +9 -1
  41. data/lib/action_controller/metal/request_forgery_protection.rb +112 -19
  42. data/lib/action_controller/metal/responder.rb +20 -19
  43. data/lib/action_controller/metal/streaming.rb +12 -18
  44. data/lib/action_controller/metal/strong_parameters.rb +520 -0
  45. data/lib/action_controller/metal/testing.rb +13 -18
  46. data/lib/action_controller/metal/url_for.rb +28 -25
  47. data/lib/action_controller/metal.rb +17 -32
  48. data/lib/action_controller/model_naming.rb +12 -0
  49. data/lib/action_controller/railtie.rb +33 -17
  50. data/lib/action_controller/railties/helpers.rb +22 -0
  51. data/lib/action_controller/record_identifier.rb +18 -72
  52. data/lib/action_controller/test_case.rb +251 -131
  53. data/lib/action_controller/vendor/html-scanner.rb +4 -19
  54. data/lib/action_controller.rb +15 -6
  55. data/lib/action_dispatch/http/cache.rb +63 -11
  56. data/lib/action_dispatch/http/filter_parameters.rb +18 -8
  57. data/lib/action_dispatch/http/filter_redirect.rb +37 -0
  58. data/lib/action_dispatch/http/headers.rb +49 -17
  59. data/lib/action_dispatch/http/mime_negotiation.rb +24 -1
  60. data/lib/action_dispatch/http/mime_type.rb +154 -100
  61. data/lib/action_dispatch/http/mime_types.rb +1 -1
  62. data/lib/action_dispatch/http/parameter_filter.rb +44 -46
  63. data/lib/action_dispatch/http/parameters.rb +28 -28
  64. data/lib/action_dispatch/http/rack_cache.rb +2 -3
  65. data/lib/action_dispatch/http/request.rb +64 -18
  66. data/lib/action_dispatch/http/response.rb +130 -35
  67. data/lib/action_dispatch/http/upload.rb +63 -20
  68. data/lib/action_dispatch/http/url.rb +98 -35
  69. data/lib/action_dispatch/journey/backwards.rb +5 -0
  70. data/lib/action_dispatch/journey/formatter.rb +146 -0
  71. data/lib/action_dispatch/journey/gtg/builder.rb +162 -0
  72. data/lib/action_dispatch/journey/gtg/simulator.rb +44 -0
  73. data/lib/action_dispatch/journey/gtg/transition_table.rb +156 -0
  74. data/lib/action_dispatch/journey/nfa/builder.rb +76 -0
  75. data/lib/action_dispatch/journey/nfa/dot.rb +36 -0
  76. data/lib/action_dispatch/journey/nfa/simulator.rb +47 -0
  77. data/lib/action_dispatch/journey/nfa/transition_table.rb +163 -0
  78. data/lib/action_dispatch/journey/nodes/node.rb +124 -0
  79. data/lib/action_dispatch/journey/parser.rb +206 -0
  80. data/lib/action_dispatch/journey/parser.y +47 -0
  81. data/lib/action_dispatch/journey/parser_extras.rb +23 -0
  82. data/lib/action_dispatch/journey/path/pattern.rb +196 -0
  83. data/lib/action_dispatch/journey/route.rb +124 -0
  84. data/lib/action_dispatch/journey/router/strexp.rb +24 -0
  85. data/lib/action_dispatch/journey/router/utils.rb +54 -0
  86. data/lib/action_dispatch/journey/router.rb +166 -0
  87. data/lib/action_dispatch/journey/routes.rb +75 -0
  88. data/lib/action_dispatch/journey/scanner.rb +61 -0
  89. data/lib/action_dispatch/journey/visitors.rb +197 -0
  90. data/lib/action_dispatch/journey/visualizer/fsm.css +34 -0
  91. data/lib/action_dispatch/journey/visualizer/fsm.js +134 -0
  92. data/lib/action_dispatch/journey/visualizer/index.html.erb +52 -0
  93. data/lib/action_dispatch/journey.rb +5 -0
  94. data/lib/action_dispatch/middleware/callbacks.rb +9 -4
  95. data/lib/action_dispatch/middleware/cookies.rb +259 -114
  96. data/lib/action_dispatch/middleware/debug_exceptions.rb +26 -17
  97. data/lib/action_dispatch/middleware/exception_wrapper.rb +29 -3
  98. data/lib/action_dispatch/middleware/flash.rb +58 -58
  99. data/lib/action_dispatch/middleware/params_parser.rb +14 -29
  100. data/lib/action_dispatch/middleware/public_exceptions.rb +30 -14
  101. data/lib/action_dispatch/middleware/reloader.rb +6 -6
  102. data/lib/action_dispatch/middleware/remote_ip.rb +145 -39
  103. data/lib/action_dispatch/middleware/request_id.rb +2 -6
  104. data/lib/action_dispatch/middleware/session/abstract_store.rb +22 -20
  105. data/lib/action_dispatch/middleware/session/cookie_store.rb +82 -28
  106. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +8 -3
  107. data/lib/action_dispatch/middleware/show_exceptions.rb +12 -45
  108. data/lib/action_dispatch/middleware/ssl.rb +70 -0
  109. data/lib/action_dispatch/middleware/stack.rb +6 -1
  110. data/lib/action_dispatch/middleware/static.rb +2 -1
  111. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb +14 -11
  112. data/lib/action_dispatch/middleware/templates/rescues/_source.erb +25 -0
  113. data/lib/action_dispatch/middleware/templates/rescues/_trace.erb +7 -9
  114. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb +15 -9
  115. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +127 -5
  116. data/lib/action_dispatch/middleware/templates/rescues/missing_template.erb +7 -2
  117. data/lib/action_dispatch/middleware/templates/rescues/routing_error.erb +30 -15
  118. data/lib/action_dispatch/middleware/templates/rescues/template_error.erb +39 -13
  119. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.erb +6 -2
  120. data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +16 -0
  121. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +144 -0
  122. data/lib/action_dispatch/railtie.rb +16 -6
  123. data/lib/action_dispatch/request/session.rb +181 -0
  124. data/lib/action_dispatch/routing/inspector.rb +240 -0
  125. data/lib/action_dispatch/routing/mapper.rb +540 -291
  126. data/lib/action_dispatch/routing/polymorphic_routes.rb +16 -20
  127. data/lib/action_dispatch/routing/redirection.rb +46 -29
  128. data/lib/action_dispatch/routing/route_set.rb +207 -164
  129. data/lib/action_dispatch/routing/routes_proxy.rb +2 -0
  130. data/lib/action_dispatch/routing/url_for.rb +48 -33
  131. data/lib/action_dispatch/routing.rb +48 -83
  132. data/lib/action_dispatch/testing/assertions/dom.rb +3 -13
  133. data/lib/action_dispatch/testing/assertions/response.rb +32 -40
  134. data/lib/action_dispatch/testing/assertions/routing.rb +42 -41
  135. data/lib/action_dispatch/testing/assertions/selector.rb +17 -22
  136. data/lib/action_dispatch/testing/assertions/tag.rb +20 -23
  137. data/lib/action_dispatch/testing/integration.rb +65 -51
  138. data/lib/action_dispatch/testing/test_process.rb +9 -6
  139. data/lib/action_dispatch/testing/test_request.rb +7 -3
  140. data/lib/action_dispatch.rb +21 -15
  141. data/lib/action_pack/version.rb +7 -6
  142. data/lib/action_pack.rb +1 -1
  143. data/lib/action_view/base.rb +15 -34
  144. data/lib/action_view/buffers.rb +7 -1
  145. data/lib/action_view/context.rb +4 -4
  146. data/lib/action_view/dependency_tracker.rb +93 -0
  147. data/lib/action_view/digestor.rb +85 -0
  148. data/lib/action_view/flows.rb +1 -4
  149. data/lib/action_view/helpers/active_model_helper.rb +3 -4
  150. data/lib/action_view/helpers/asset_tag_helper.rb +215 -352
  151. data/lib/action_view/helpers/asset_url_helper.rb +355 -0
  152. data/lib/action_view/helpers/atom_feed_helper.rb +13 -10
  153. data/lib/action_view/helpers/cache_helper.rb +150 -18
  154. data/lib/action_view/helpers/capture_helper.rb +44 -31
  155. data/lib/action_view/helpers/csrf_helper.rb +0 -2
  156. data/lib/action_view/helpers/date_helper.rb +269 -248
  157. data/lib/action_view/helpers/debug_helper.rb +10 -11
  158. data/lib/action_view/helpers/form_helper.rb +931 -537
  159. data/lib/action_view/helpers/form_options_helper.rb +341 -166
  160. data/lib/action_view/helpers/form_tag_helper.rb +190 -90
  161. data/lib/action_view/helpers/javascript_helper.rb +23 -16
  162. data/lib/action_view/helpers/number_helper.rb +148 -329
  163. data/lib/action_view/helpers/output_safety_helper.rb +3 -3
  164. data/lib/action_view/helpers/record_tag_helper.rb +17 -22
  165. data/lib/action_view/helpers/rendering_helper.rb +2 -2
  166. data/lib/action_view/helpers/sanitize_helper.rb +3 -6
  167. data/lib/action_view/helpers/tag_helper.rb +46 -33
  168. data/lib/action_view/helpers/tags/base.rb +147 -0
  169. data/lib/action_view/helpers/tags/check_box.rb +64 -0
  170. data/lib/action_view/helpers/tags/checkable.rb +16 -0
  171. data/lib/action_view/helpers/tags/collection_check_boxes.rb +43 -0
  172. data/lib/action_view/helpers/tags/collection_helpers.rb +83 -0
  173. data/lib/action_view/helpers/tags/collection_radio_buttons.rb +36 -0
  174. data/lib/action_view/helpers/tags/collection_select.rb +28 -0
  175. data/lib/action_view/helpers/tags/color_field.rb +25 -0
  176. data/lib/action_view/helpers/tags/date_field.rb +13 -0
  177. data/lib/action_view/helpers/tags/date_select.rb +72 -0
  178. data/lib/action_view/helpers/tags/datetime_field.rb +22 -0
  179. data/lib/action_view/helpers/tags/datetime_local_field.rb +19 -0
  180. data/lib/action_view/helpers/tags/datetime_select.rb +8 -0
  181. data/lib/action_view/helpers/tags/email_field.rb +8 -0
  182. data/lib/action_view/helpers/tags/file_field.rb +8 -0
  183. data/lib/action_view/helpers/tags/grouped_collection_select.rb +29 -0
  184. data/lib/action_view/helpers/tags/hidden_field.rb +8 -0
  185. data/lib/action_view/helpers/tags/label.rb +65 -0
  186. data/lib/action_view/helpers/tags/month_field.rb +13 -0
  187. data/lib/action_view/helpers/tags/number_field.rb +18 -0
  188. data/lib/action_view/helpers/tags/password_field.rb +12 -0
  189. data/lib/action_view/helpers/tags/radio_button.rb +31 -0
  190. data/lib/action_view/helpers/tags/range_field.rb +8 -0
  191. data/lib/action_view/helpers/tags/search_field.rb +24 -0
  192. data/lib/action_view/helpers/tags/select.rb +40 -0
  193. data/lib/action_view/helpers/tags/tel_field.rb +8 -0
  194. data/lib/action_view/helpers/tags/text_area.rb +18 -0
  195. data/lib/action_view/helpers/tags/text_field.rb +29 -0
  196. data/lib/action_view/helpers/tags/time_field.rb +13 -0
  197. data/lib/action_view/helpers/tags/time_select.rb +8 -0
  198. data/lib/action_view/helpers/tags/time_zone_select.rb +20 -0
  199. data/lib/action_view/helpers/tags/url_field.rb +8 -0
  200. data/lib/action_view/helpers/tags/week_field.rb +13 -0
  201. data/lib/action_view/helpers/tags.rb +39 -0
  202. data/lib/action_view/helpers/text_helper.rb +130 -114
  203. data/lib/action_view/helpers/translation_helper.rb +32 -16
  204. data/lib/action_view/helpers/url_helper.rb +211 -270
  205. data/lib/action_view/helpers.rb +2 -4
  206. data/lib/action_view/locale/en.yml +1 -105
  207. data/lib/action_view/log_subscriber.rb +6 -4
  208. data/lib/action_view/lookup_context.rb +15 -28
  209. data/lib/action_view/model_naming.rb +12 -0
  210. data/lib/action_view/path_set.rb +8 -20
  211. data/lib/action_view/railtie.rb +6 -22
  212. data/lib/action_view/record_identifier.rb +84 -0
  213. data/lib/action_view/renderer/abstract_renderer.rb +25 -19
  214. data/lib/action_view/renderer/partial_renderer.rb +158 -81
  215. data/lib/action_view/renderer/renderer.rb +8 -12
  216. data/lib/action_view/renderer/streaming_template_renderer.rb +2 -5
  217. data/lib/action_view/renderer/template_renderer.rb +12 -10
  218. data/lib/action_view/routing_url_for.rb +107 -0
  219. data/lib/action_view/template/error.rb +22 -12
  220. data/lib/action_view/template/handlers/builder.rb +1 -1
  221. data/lib/action_view/template/handlers/erb.rb +40 -19
  222. data/lib/action_view/template/handlers/raw.rb +11 -0
  223. data/lib/action_view/template/handlers.rb +12 -9
  224. data/lib/action_view/template/resolver.rb +107 -53
  225. data/lib/action_view/template/text.rb +12 -8
  226. data/lib/action_view/template/types.rb +57 -0
  227. data/lib/action_view/template.rb +25 -23
  228. data/lib/action_view/test_case.rb +67 -42
  229. data/lib/{action_controller → action_view}/vendor/html-scanner/html/document.rb +0 -0
  230. data/lib/{action_controller → action_view}/vendor/html-scanner/html/node.rb +12 -12
  231. data/lib/{action_controller → action_view}/vendor/html-scanner/html/sanitizer.rb +13 -2
  232. data/lib/{action_controller → action_view}/vendor/html-scanner/html/selector.rb +9 -9
  233. data/lib/{action_controller → action_view}/vendor/html-scanner/html/tokenizer.rb +1 -1
  234. data/lib/{action_controller → action_view}/vendor/html-scanner/html/version.rb +0 -0
  235. data/lib/action_view/vendor/html-scanner.rb +20 -0
  236. data/lib/action_view.rb +17 -8
  237. metadata +184 -214
  238. data/lib/action_controller/caching/actions.rb +0 -185
  239. data/lib/action_controller/caching/pages.rb +0 -187
  240. data/lib/action_controller/caching/sweeping.rb +0 -97
  241. data/lib/action_controller/deprecated/performance_test.rb +0 -1
  242. data/lib/action_controller/metal/compatibility.rb +0 -65
  243. data/lib/action_controller/metal/session_management.rb +0 -14
  244. data/lib/action_controller/railties/paths.rb +0 -25
  245. data/lib/action_dispatch/middleware/best_standards_support.rb +0 -30
  246. data/lib/action_dispatch/middleware/body_proxy.rb +0 -30
  247. data/lib/action_dispatch/middleware/head.rb +0 -18
  248. data/lib/action_dispatch/middleware/rescue.rb +0 -26
  249. data/lib/action_dispatch/testing/performance_test.rb +0 -10
  250. data/lib/action_view/asset_paths.rb +0 -142
  251. data/lib/action_view/helpers/asset_paths.rb +0 -7
  252. data/lib/action_view/helpers/asset_tag_helpers/asset_include_tag.rb +0 -146
  253. data/lib/action_view/helpers/asset_tag_helpers/asset_paths.rb +0 -93
  254. data/lib/action_view/helpers/asset_tag_helpers/javascript_tag_helpers.rb +0 -193
  255. data/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb +0 -148
  256. data/lib/sprockets/assets.rake +0 -99
  257. data/lib/sprockets/bootstrap.rb +0 -37
  258. data/lib/sprockets/compressors.rb +0 -83
  259. data/lib/sprockets/helpers/isolated_helper.rb +0 -13
  260. data/lib/sprockets/helpers/rails_helper.rb +0 -182
  261. data/lib/sprockets/helpers.rb +0 -6
  262. data/lib/sprockets/railtie.rb +0 -62
  263. data/lib/sprockets/static_compiler.rb +0 -56
@@ -1,12 +1,16 @@
1
- require 'tempfile'
2
1
  require 'stringio'
3
- require 'strscan'
4
2
 
5
- require 'active_support/core_ext/hash/indifferent_access'
6
- require 'active_support/core_ext/string/access'
7
3
  require 'active_support/inflector'
8
4
  require 'action_dispatch/http/headers'
9
5
  require 'action_controller/metal/exceptions'
6
+ require 'rack/request'
7
+ require 'action_dispatch/http/cache'
8
+ require 'action_dispatch/http/mime_negotiation'
9
+ require 'action_dispatch/http/parameters'
10
+ require 'action_dispatch/http/filter_parameters'
11
+ require 'action_dispatch/http/upload'
12
+ require 'action_dispatch/http/url'
13
+ require 'active_support/core_ext/array/conversions'
10
14
 
11
15
  module ActionDispatch
12
16
  class Request < Rack::Request
@@ -17,7 +21,10 @@ module ActionDispatch
17
21
  include ActionDispatch::Http::Upload
18
22
  include ActionDispatch::Http::URL
19
23
 
20
- LOCALHOST = [/^127\.0\.0\.\d{1,3}$/, "::1", /^0:0:0:0:0:0:0:1(%.*)?$/].freeze
24
+ autoload :Session, 'action_dispatch/request/session'
25
+
26
+ LOCALHOST = Regexp.union [/^127\.0\.0\.\d{1,3}$/, /^::1$/, /^0:0:0:0:0:0:0:1(%.*)?$/]
27
+
21
28
  ENV_METHODS = %w[ AUTH_TYPE GATEWAY_INTERFACE
22
29
  PATH_TRANSLATED REMOTE_HOST
23
30
  REMOTE_IDENT REMOTE_USER REMOTE_ADDR
@@ -35,6 +42,17 @@ module ActionDispatch
35
42
  METHOD
36
43
  end
37
44
 
45
+ def initialize(env)
46
+ super
47
+ @method = nil
48
+ @request_method = nil
49
+ @remote_ip = nil
50
+ @original_fullpath = nil
51
+ @fullpath = nil
52
+ @ip = nil
53
+ @uuid = nil
54
+ end
55
+
38
56
  def key?(key)
39
57
  @env.key?(key)
40
58
  end
@@ -56,12 +74,13 @@ module ActionDispatch
56
74
  RFC5789 = %w(PATCH)
57
75
 
58
76
  HTTP_METHODS = RFC2616 + RFC2518 + RFC3253 + RFC3648 + RFC3744 + RFC5323 + RFC5789
77
+
59
78
  HTTP_METHOD_LOOKUP = {}
60
79
 
61
80
  # Populate the HTTP method lookup cache
62
- HTTP_METHODS.each do |method|
81
+ HTTP_METHODS.each { |method|
63
82
  HTTP_METHOD_LOOKUP[method] = method.underscore.to_sym
64
- end
83
+ }
65
84
 
66
85
  # Returns the HTTP \method that the application should see.
67
86
  # In the case where the \method was overridden by a middleware
@@ -102,6 +121,12 @@ module ActionDispatch
102
121
  HTTP_METHOD_LOOKUP[request_method] == :post
103
122
  end
104
123
 
124
+ # Is this a PATCH request?
125
+ # Equivalent to <tt>request.request_method == :patch</tt>.
126
+ def patch?
127
+ HTTP_METHOD_LOOKUP[request_method] == :patch
128
+ end
129
+
105
130
  # Is this a PUT request?
106
131
  # Equivalent to <tt>request.request_method_symbol == :put</tt>.
107
132
  def put?
@@ -115,9 +140,9 @@ module ActionDispatch
115
140
  end
116
141
 
117
142
  # Is this a HEAD request?
118
- # Equivalent to <tt>request.method_symbol == :head</tt>.
143
+ # Equivalent to <tt>request.request_method_symbol == :head</tt>.
119
144
  def head?
120
- HTTP_METHOD_LOOKUP[method] == :head
145
+ HTTP_METHOD_LOOKUP[request_method] == :head
121
146
  end
122
147
 
123
148
  # Provides access to the request's HTTP headers, for example:
@@ -131,14 +156,29 @@ module ActionDispatch
131
156
  @original_fullpath ||= (env["ORIGINAL_FULLPATH"] || fullpath)
132
157
  end
133
158
 
159
+ # Returns the +String+ full path including params of the last URL requested.
160
+ #
161
+ # # get "/articles"
162
+ # request.fullpath # => "/articles"
163
+ #
164
+ # # get "/articles?page=2"
165
+ # request.fullpath # => "/articles?page=2"
134
166
  def fullpath
135
167
  @fullpath ||= super
136
168
  end
137
169
 
170
+ # Returns the original request URL as a +String+.
171
+ #
172
+ # # get "/articles?page=2"
173
+ # request.original_url # => "http://www.example.com/articles?page=2"
138
174
  def original_url
139
175
  base_url + original_fullpath
140
176
  end
141
177
 
178
+ # The +String+ MIME type of the request.
179
+ #
180
+ # # get "/articles"
181
+ # request.media_type # => "application/x-www-form-urlencoded"
142
182
  def media_type
143
183
  content_mime_type.to_s
144
184
  end
@@ -195,7 +235,7 @@ module ActionDispatch
195
235
  # variable is already set, wrap it in a StringIO.
196
236
  def body
197
237
  if raw_post = @env['RAW_POST_DATA']
198
- raw_post.force_encoding(Encoding::BINARY) if raw_post.respond_to?(:force_encoding)
238
+ raw_post.force_encoding(Encoding::BINARY)
199
239
  StringIO.new(raw_post)
200
240
  else
201
241
  @env['rack.input']
@@ -213,32 +253,38 @@ module ActionDispatch
213
253
  # TODO This should be broken apart into AD::Request::Session and probably
214
254
  # be included by the session middleware.
215
255
  def reset_session
216
- session.destroy if session && session.respond_to?(:destroy)
217
- self.session = {}
256
+ if session && session.respond_to?(:destroy)
257
+ session.destroy
258
+ else
259
+ self.session = {}
260
+ end
218
261
  @env['action_dispatch.request.flash_hash'] = nil
219
262
  end
220
263
 
221
264
  def session=(session) #:nodoc:
222
- @env['rack.session'] = session
265
+ Session.set @env, session
223
266
  end
224
267
 
225
268
  def session_options=(options)
226
- @env['rack.session.options'] = options
269
+ Session::Options.set @env, options
227
270
  end
228
271
 
229
272
  # Override Rack's GET method to support indifferent access
230
273
  def GET
231
- @env["action_dispatch.request.query_parameters"] ||= deep_munge(normalize_parameters(super) || {})
274
+ @env["action_dispatch.request.query_parameters"] ||= (normalize_encode_params(super) || {})
275
+ rescue TypeError => e
276
+ raise ActionController::BadRequest.new(:query, e)
232
277
  end
233
278
  alias :query_parameters :GET
234
279
 
235
280
  # Override Rack's POST method to support indifferent access
236
281
  def POST
237
- @env["action_dispatch.request.request_parameters"] ||= deep_munge(normalize_parameters(super) || {})
282
+ @env["action_dispatch.request.request_parameters"] ||= (normalize_encode_params(super) || {})
283
+ rescue TypeError => e
284
+ raise ActionController::BadRequest.new(:request, e)
238
285
  end
239
286
  alias :request_parameters :POST
240
287
 
241
-
242
288
  # Returns the authorization header regardless of whether it was specified directly or through one of the
243
289
  # proxy alternatives.
244
290
  def authorization
@@ -250,7 +296,7 @@ module ActionDispatch
250
296
 
251
297
  # True if the request came from localhost, 127.0.0.1.
252
298
  def local?
253
- LOCALHOST.any? { |local_ip| local_ip === remote_addr && local_ip === remote_ip }
299
+ LOCALHOST =~ remote_addr && LOCALHOST =~ remote_ip
254
300
  end
255
301
 
256
302
  # Remove nils from the params hash
@@ -1,7 +1,5 @@
1
- require 'digest/md5'
2
- require 'active_support/core_ext/module/delegation'
3
- require 'active_support/core_ext/object/blank'
4
1
  require 'active_support/core_ext/class/attribute_accessors'
2
+ require 'monitor'
5
3
 
6
4
  module ActionDispatch # :nodoc:
7
5
  # Represents an HTTP response generated by a controller action. Use it to
@@ -29,7 +27,7 @@ module ActionDispatch # :nodoc:
29
27
  # class DemoControllerTest < ActionDispatch::IntegrationTest
30
28
  # def test_print_root_path_to_console
31
29
  # get('/')
32
- # puts @response.body
30
+ # puts response.body
33
31
  # end
34
32
  # end
35
33
  class Response
@@ -41,7 +39,7 @@ module ActionDispatch # :nodoc:
41
39
  alias_method :headers, :header
42
40
 
43
41
  delegate :[], :[]=, :to => :@header
44
- delegate :each, :to => :@body
42
+ delegate :each, :to => :@stream
45
43
 
46
44
  # Sets the HTTP response's content MIME type. For example, in the controller
47
45
  # you could write this:
@@ -51,22 +49,65 @@ module ActionDispatch # :nodoc:
51
49
  # If a character set has been defined for this response (see charset=) then
52
50
  # the character set information will also be included in the content type
53
51
  # information.
54
- attr_accessor :charset, :content_type
52
+ attr_accessor :charset
53
+ attr_reader :content_type
55
54
 
56
55
  CONTENT_TYPE = "Content-Type".freeze
57
56
  SET_COOKIE = "Set-Cookie".freeze
58
57
  LOCATION = "Location".freeze
59
-
58
+ NO_CONTENT_CODES = [204, 304]
59
+
60
60
  cattr_accessor(:default_charset) { "utf-8" }
61
+ cattr_accessor(:default_headers)
61
62
 
62
63
  include Rack::Response::Helpers
64
+ include ActionDispatch::Http::FilterRedirect
63
65
  include ActionDispatch::Http::Cache::Response
66
+ include MonitorMixin
67
+
68
+ class Buffer # :nodoc:
69
+ def initialize(response, buf)
70
+ @response = response
71
+ @buf = buf
72
+ @closed = false
73
+ end
74
+
75
+ def write(string)
76
+ raise IOError, "closed stream" if closed?
77
+
78
+ @response.commit!
79
+ @buf.push string
80
+ end
81
+
82
+ def each(&block)
83
+ @buf.each(&block)
84
+ end
85
+
86
+ def close
87
+ @response.commit!
88
+ @closed = true
89
+ end
90
+
91
+ def closed?
92
+ @closed
93
+ end
94
+ end
95
+
96
+ attr_reader :stream
64
97
 
65
98
  def initialize(status = 200, header = {}, body = [])
99
+ super()
100
+
101
+ header = merge_default_headers(header, self.class.default_headers)
102
+
66
103
  self.body, self.header, self.status = body, header, status
67
104
 
68
105
  @sending_file = false
69
- @blank = false
106
+ @blank = false
107
+ @cv = new_cond
108
+ @committed = false
109
+ @content_type = nil
110
+ @charset = nil
70
111
 
71
112
  if content_type = self[CONTENT_TYPE]
72
113
  type, charset = content_type.split(/;\s*charset=/)
@@ -79,37 +120,69 @@ module ActionDispatch # :nodoc:
79
120
  yield self if block_given?
80
121
  end
81
122
 
123
+ def await_commit
124
+ synchronize do
125
+ @cv.wait_until { @committed }
126
+ end
127
+ end
128
+
129
+ def commit!
130
+ synchronize do
131
+ @committed = true
132
+ @cv.broadcast
133
+ end
134
+ end
135
+
136
+ def committed?
137
+ @committed
138
+ end
139
+
140
+ # Sets the HTTP status code.
82
141
  def status=(status)
83
142
  @status = Rack::Utils.status_code(status)
84
143
  end
85
144
 
86
- # The response code of the request
145
+ def content_type=(content_type)
146
+ @content_type = content_type.to_s
147
+ end
148
+
149
+ # The response code of the request.
87
150
  def response_code
88
151
  @status
89
152
  end
90
153
 
91
- # Returns a String to ensure compatibility with Net::HTTPResponse
154
+ # Returns a string to ensure compatibility with <tt>Net::HTTPResponse</tt>.
92
155
  def code
93
156
  @status.to_s
94
157
  end
95
158
 
159
+ # Returns the corresponding message for the current HTTP status code:
160
+ #
161
+ # response.status = 200
162
+ # response.message # => "OK"
163
+ #
164
+ # response.status = 404
165
+ # response.message # => "Not Found"
166
+ #
96
167
  def message
97
168
  Rack::Utils::HTTP_STATUS_CODES[@status]
98
169
  end
99
170
  alias_method :status_message, :message
100
171
 
101
172
  def respond_to?(method)
102
- if method.to_sym == :to_path
103
- @body.respond_to?(:to_path)
173
+ if method.to_s == 'to_path'
174
+ stream.respond_to?(:to_path)
104
175
  else
105
176
  super
106
177
  end
107
178
  end
108
179
 
109
180
  def to_path
110
- @body.to_path
181
+ stream.to_path
111
182
  end
112
183
 
184
+ # Returns the content of the response as a string. This contains the contents
185
+ # of any calls to <tt>render</tt>.
113
186
  def body
114
187
  strings = []
115
188
  each { |part| strings << part.to_s }
@@ -118,21 +191,21 @@ module ActionDispatch # :nodoc:
118
191
 
119
192
  EMPTY = " "
120
193
 
194
+ # Allows you to manually set or override the response body.
121
195
  def body=(body)
122
196
  @blank = true if body == EMPTY
123
197
 
124
- # Explicitly check for strings. This is *wrong* theoretically
125
- # but if we don't check this, the performance on string bodies
126
- # is bad on Ruby 1.8 (because strings responds to each then).
127
- @body = if body.respond_to?(:to_str) || !body.respond_to?(:each)
128
- [body]
198
+ if body.respond_to?(:to_path)
199
+ @stream = body
129
200
  else
130
- body
201
+ @stream = build_buffer self, munge_body_object(body)
131
202
  end
132
203
  end
133
204
 
134
205
  def body_parts
135
- @body
206
+ parts = []
207
+ @stream.each { |x| parts << x }
208
+ parts
136
209
  end
137
210
 
138
211
  def set_cookie(key, value)
@@ -153,21 +226,11 @@ module ActionDispatch # :nodoc:
153
226
  end
154
227
 
155
228
  def close
156
- @body.close if @body.respond_to?(:close)
229
+ stream.close if stream.respond_to?(:close)
157
230
  end
158
231
 
159
232
  def to_a
160
- assign_default_content_type_and_charset!
161
- handle_conditional_get!
162
-
163
- @header[SET_COOKIE] = @header[SET_COOKIE].join("\n") if @header[SET_COOKIE].respond_to?(:join)
164
-
165
- if [204, 304].include?(@status)
166
- @header.delete CONTENT_TYPE
167
- [@status, @header, []]
168
- else
169
- [@status, @header, self]
170
- end
233
+ rack_response @status, @header.to_hash
171
234
  end
172
235
  alias prepare! to_a
173
236
  alias to_ary to_a # For implicit splat on 1.9.2
@@ -191,16 +254,48 @@ module ActionDispatch # :nodoc:
191
254
 
192
255
  private
193
256
 
194
- def assign_default_content_type_and_charset!
257
+ def merge_default_headers(original, default)
258
+ return original unless default.respond_to?(:merge)
259
+
260
+ default.merge(original)
261
+ end
262
+
263
+ def build_buffer(response, body)
264
+ Buffer.new response, body
265
+ end
266
+
267
+ def munge_body_object(body)
268
+ body.respond_to?(:each) ? body : [body]
269
+ end
270
+
271
+ def assign_default_content_type_and_charset!(headers)
195
272
  return if headers[CONTENT_TYPE].present?
196
273
 
197
274
  @content_type ||= Mime::HTML
198
- @charset ||= self.class.default_charset
275
+ @charset ||= self.class.default_charset unless @charset == false
199
276
 
200
277
  type = @content_type.to_s.dup
201
- type << "; charset=#{@charset}" unless @sending_file
278
+ type << "; charset=#{@charset}" if append_charset?
202
279
 
203
280
  headers[CONTENT_TYPE] = type
204
281
  end
282
+
283
+ def append_charset?
284
+ !@sending_file && @charset != false
285
+ end
286
+
287
+ def rack_response(status, header)
288
+ assign_default_content_type_and_charset!(header)
289
+ handle_conditional_get!
290
+
291
+ header[SET_COOKIE] = header[SET_COOKIE].join("\n") if header[SET_COOKIE].respond_to?(:join)
292
+
293
+ if NO_CONTENT_CODES.include?(@status)
294
+ header.delete CONTENT_TYPE
295
+ [status, header, []]
296
+ else
297
+ [status, header, self]
298
+ end
299
+ end
205
300
  end
206
301
  end
@@ -1,47 +1,90 @@
1
1
  module ActionDispatch
2
2
  module Http
3
+ # Models uploaded files.
4
+ #
5
+ # The actual file is accessible via the +tempfile+ accessor, though some
6
+ # of its interface is available directly for convenience.
7
+ #
8
+ # Uploaded files are temporary files whose lifespan is one request. When
9
+ # the object is finalized Ruby unlinks the file, so there is no need to
10
+ # clean them with a separate maintenance task.
3
11
  class UploadedFile
4
- attr_accessor :original_filename, :content_type, :tempfile, :headers
12
+ # The basename of the file in the client.
13
+ attr_accessor :original_filename
14
+
15
+ # A string with the MIME type of the file.
16
+ attr_accessor :content_type
17
+
18
+ # A +Tempfile+ object with the actual uploaded file. Note that some of
19
+ # its interface is available directly.
20
+ attr_accessor :tempfile
21
+
22
+ # A string with the headers of the multipart request.
23
+ attr_accessor :headers
24
+
25
+ def initialize(hash) # :nodoc:
26
+ @tempfile = hash[:tempfile]
27
+ raise(ArgumentError, ':tempfile is required') unless @tempfile
5
28
 
6
- def initialize(hash)
7
29
  @original_filename = encode_filename(hash[:filename])
8
30
  @content_type = hash[:type]
9
31
  @headers = hash[:head]
10
- @tempfile = hash[:tempfile]
11
- raise(ArgumentError, ':tempfile is required') unless @tempfile
12
32
  end
13
33
 
14
- def read(*args)
15
- @tempfile.read(*args)
34
+ # Shortcut for +tempfile.read+.
35
+ def read(length=nil, buffer=nil)
36
+ @tempfile.read(length, buffer)
16
37
  end
17
38
 
18
- # Delegate these methods to the tempfile.
19
- [:open, :path, :rewind, :size].each do |method|
20
- class_eval "def #{method}; @tempfile.#{method}; end"
39
+ # Shortcut for +tempfile.open+.
40
+ def open
41
+ @tempfile.open
42
+ end
43
+
44
+ # Shortcut for +tempfile.close+.
45
+ def close(unlink_now=false)
46
+ @tempfile.close(unlink_now)
47
+ end
48
+
49
+ # Shortcut for +tempfile.path+.
50
+ def path
51
+ @tempfile.path
52
+ end
53
+
54
+ # Shortcut for +tempfile.rewind+.
55
+ def rewind
56
+ @tempfile.rewind
57
+ end
58
+
59
+ # Shortcut for +tempfile.size+.
60
+ def size
61
+ @tempfile.size
62
+ end
63
+
64
+ # Shortcut for +tempfile.eof?+.
65
+ def eof?
66
+ @tempfile.eof?
21
67
  end
22
68
 
23
69
  private
70
+
24
71
  def encode_filename(filename)
25
- # Encode the filename in the utf8 encoding, unless it is nil or we're in 1.8
26
- if "ruby".encoding_aware? && filename
27
- filename.force_encoding("UTF-8").encode!
28
- else
29
- filename
30
- end
72
+ # Encode the filename in the utf8 encoding, unless it is nil
73
+ filename.force_encoding(Encoding::UTF_8).encode! if filename
31
74
  end
32
75
  end
33
76
 
34
- module Upload
35
- # Convert nested Hash to HashWithIndifferentAccess and replace
36
- # file upload hash with UploadedFile objects
37
- def normalize_parameters(value)
77
+ module Upload # :nodoc:
78
+ # Replace file upload hash with UploadedFile objects
79
+ # when normalize and encode parameters.
80
+ def normalize_encode_params(value)
38
81
  if Hash === value && value.has_key?(:tempfile)
39
82
  UploadedFile.new(value)
40
83
  else
41
84
  super
42
85
  end
43
86
  end
44
- private :normalize_parameters
87
+ private :normalize_encode_params
45
88
  end
46
89
  end
47
90
  end