actionpack 1.11.2 → 1.12.0
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.
- data/CHANGELOG +392 -5
- data/lib/action_controller.rb +8 -4
- data/lib/action_controller/assertions.rb +9 -10
- data/lib/action_controller/base.rb +177 -88
- data/lib/action_controller/benchmarking.rb +5 -5
- data/lib/action_controller/caching.rb +44 -36
- data/lib/action_controller/cgi_ext/cgi_methods.rb +71 -6
- data/lib/action_controller/cgi_ext/cookie_performance_fix.rb +1 -1
- data/lib/action_controller/cgi_process.rb +36 -24
- data/lib/action_controller/components.rb +152 -52
- data/lib/action_controller/dependencies.rb +1 -1
- data/lib/action_controller/deprecated_redirects.rb +2 -2
- data/lib/action_controller/deprecated_request_methods.rb +34 -0
- data/lib/action_controller/filters.rb +59 -19
- data/lib/action_controller/flash.rb +53 -47
- data/lib/action_controller/helpers.rb +2 -2
- data/lib/action_controller/integration.rb +524 -0
- data/lib/action_controller/layout.rb +58 -23
- data/lib/action_controller/mime_responds.rb +163 -0
- data/lib/action_controller/mime_type.rb +142 -0
- data/lib/action_controller/pagination.rb +13 -7
- data/lib/action_controller/request.rb +59 -56
- data/lib/action_controller/rescue.rb +1 -1
- data/lib/action_controller/routing.rb +29 -10
- data/lib/action_controller/scaffolding.rb +8 -0
- data/lib/action_controller/session/active_record_store.rb +21 -10
- data/lib/action_controller/session/mem_cache_store.rb +18 -12
- data/lib/action_controller/session_management.rb +30 -11
- data/lib/action_controller/templates/rescues/_trace.rhtml +1 -1
- data/lib/action_controller/templates/scaffolds/layout.rhtml +4 -4
- data/lib/action_controller/templates/scaffolds/list.rhtml +1 -1
- data/lib/action_controller/test_process.rb +189 -118
- data/lib/action_controller/vendor/html-scanner/html/node.rb +20 -1
- data/lib/action_controller/vendor/html-scanner/html/tokenizer.rb +3 -0
- data/lib/action_controller/vendor/html-scanner/html/version.rb +1 -1
- data/lib/action_controller/vendor/xml_node.rb +97 -0
- data/lib/action_controller/verification.rb +2 -0
- data/lib/action_pack/version.rb +3 -3
- data/lib/action_view.rb +0 -2
- data/lib/action_view/base.rb +109 -36
- data/lib/action_view/compiled_templates.rb +1 -1
- data/lib/action_view/helpers/active_record_helper.rb +4 -2
- data/lib/action_view/helpers/asset_tag_helper.rb +6 -7
- data/lib/action_view/helpers/capture_helper.rb +49 -12
- data/lib/action_view/helpers/date_helper.rb +14 -4
- data/lib/action_view/helpers/form_helper.rb +136 -20
- data/lib/action_view/helpers/form_options_helper.rb +29 -7
- data/lib/action_view/helpers/form_tag_helper.rb +22 -20
- data/lib/action_view/helpers/java_script_macros_helper.rb +29 -9
- data/lib/action_view/helpers/javascript_helper.rb +50 -446
- data/lib/action_view/helpers/javascripts/controls.js +95 -30
- data/lib/action_view/helpers/javascripts/dragdrop.js +161 -21
- data/lib/action_view/helpers/javascripts/effects.js +310 -211
- data/lib/action_view/helpers/javascripts/prototype.js +228 -28
- data/lib/action_view/helpers/number_helper.rb +9 -9
- data/lib/action_view/helpers/pagination_helper.rb +1 -1
- data/lib/action_view/helpers/prototype_helper.rb +900 -0
- data/lib/action_view/helpers/scriptaculous_helper.rb +135 -0
- data/lib/action_view/helpers/text_helper.rb +7 -6
- data/lib/action_view/helpers/url_helper.rb +23 -14
- data/lib/action_view/partials.rb +12 -4
- data/rakefile +13 -5
- data/test/abstract_unit.rb +4 -3
- data/test/active_record_unit.rb +88 -0
- data/test/{controller → activerecord}/active_record_assertions_test.rb +7 -50
- data/test/{controller → activerecord}/active_record_store_test.rb +27 -4
- data/test/activerecord/pagination_test.rb +161 -0
- data/test/controller/action_pack_assertions_test.rb +18 -15
- data/test/controller/base_test.rb +31 -42
- data/test/controller/benchmark_test.rb +8 -11
- data/test/controller/capture_test.rb +33 -1
- data/test/controller/cgi_test.rb +33 -0
- data/test/controller/custom_handler_test.rb +8 -0
- data/test/controller/fake_controllers.rb +9 -17
- data/test/controller/filters_test.rb +32 -3
- data/test/controller/flash_test.rb +26 -41
- data/test/controller/fragment_store_setting_test.rb +1 -1
- data/test/controller/layout_test.rb +73 -0
- data/test/controller/mime_responds_test.rb +257 -0
- data/test/controller/mime_type_test.rb +24 -0
- data/test/controller/new_render_test.rb +157 -1
- data/test/controller/redirect_test.rb +23 -0
- data/test/controller/render_test.rb +54 -56
- data/test/controller/request_test.rb +25 -0
- data/test/controller/routing_test.rb +74 -66
- data/test/controller/test_test.rb +66 -1
- data/test/controller/verification_test.rb +3 -1
- data/test/controller/webservice_test.rb +255 -0
- data/test/fixtures/companies.yml +24 -0
- data/test/fixtures/company.rb +9 -0
- data/test/fixtures/db_definitions/sqlite.sql +42 -0
- data/test/fixtures/developer.rb +7 -0
- data/test/fixtures/developers.yml +21 -0
- data/test/fixtures/developers_projects.yml +13 -0
- data/test/fixtures/layout_tests/layouts/controller_name_space/nested.rhtml +1 -0
- data/test/fixtures/layout_tests/layouts/item.rhtml +1 -0
- data/test/fixtures/layout_tests/layouts/layout_test.rhtml +1 -0
- data/test/fixtures/layout_tests/layouts/third_party_template_library.mab +1 -0
- data/test/fixtures/layout_tests/views/hello.rhtml +1 -0
- data/test/fixtures/multipart/mona_lisa.jpg +0 -0
- data/test/fixtures/project.rb +3 -0
- data/test/fixtures/projects.yml +7 -0
- data/test/fixtures/replies.yml +13 -0
- data/test/fixtures/reply.rb +5 -0
- data/test/fixtures/respond_to/all_types_with_layout.rhtml +1 -0
- data/test/fixtures/respond_to/all_types_with_layout.rjs +1 -0
- data/test/fixtures/respond_to/layouts/standard.rhtml +1 -0
- data/test/fixtures/respond_to/using_defaults.rhtml +1 -0
- data/test/fixtures/respond_to/using_defaults.rjs +1 -0
- data/test/fixtures/respond_to/using_defaults.rxml +1 -0
- data/test/fixtures/respond_to/using_defaults_with_type_list.rhtml +1 -0
- data/test/fixtures/respond_to/using_defaults_with_type_list.rjs +1 -0
- data/test/fixtures/respond_to/using_defaults_with_type_list.rxml +1 -0
- data/test/fixtures/test/block_content_for.rhtml +2 -0
- data/test/fixtures/test/delete_with_js.rjs +2 -0
- data/test/fixtures/test/dot.directory/render_file_with_ivar.rhtml +1 -0
- data/test/fixtures/test/enum_rjs_test.rjs +6 -0
- data/test/fixtures/test/erb_content_for.rhtml +2 -0
- data/test/fixtures/test/hello_world.rxml +3 -0
- data/test/fixtures/test/hello_world_with_layout_false.rhtml +1 -0
- data/test/fixtures/test/non_erb_block_content_for.rxml +4 -0
- data/test/fixtures/topic.rb +3 -0
- data/test/fixtures/topics.yml +22 -0
- data/test/template/active_record_helper_test.rb +4 -0
- data/test/template/asset_tag_helper_test.rb +7 -2
- data/test/template/date_helper_test.rb +39 -2
- data/test/template/form_helper_test.rb +238 -5
- data/test/template/form_options_helper_test.rb +78 -0
- data/test/template/form_tag_helper_test.rb +11 -0
- data/test/template/java_script_macros_helper_test.rb +51 -6
- data/test/template/javascript_helper_test.rb +7 -153
- data/test/template/number_helper_test.rb +14 -13
- data/test/template/prototype_helper_test.rb +423 -0
- data/test/template/scriptaculous_helper_test.rb +90 -0
- data/test/template/text_helper_test.rb +12 -9
- data/test/template/url_helper_test.rb +31 -15
- metadata +291 -246
- data/lib/action_controller/cgi_ext/multipart_progress.rb +0 -169
- data/lib/action_controller/upload_progress.rb +0 -473
- data/lib/action_controller/vendor/html-scanner/html/node.rb.rej +0 -17
- data/lib/action_view/helpers/upload_progress_helper.rb +0 -433
- data/lib/action_view/vendor/builder.rb +0 -13
- data/lib/action_view/vendor/builder/blankslate.rb +0 -53
- data/lib/action_view/vendor/builder/xmlbase.rb +0 -143
- data/lib/action_view/vendor/builder/xmlevents.rb +0 -63
- data/lib/action_view/vendor/builder/xmlmarkup.rb +0 -308
- data/test/controller/multipart_progress_testx.rb +0 -365
- data/test/controller/upload_progress_testx.rb +0 -89
- data/test/template/upload_progress_helper_testx.rb +0 -136
@@ -4,9 +4,9 @@ module ActionController #:nodoc:
|
|
4
4
|
# The benchmarking module times the performance of actions and reports to the logger. If the Active Record
|
5
5
|
# package has been included, a separate timing section for database calls will be added as well.
|
6
6
|
module Benchmarking #:nodoc:
|
7
|
-
def self.
|
8
|
-
super
|
7
|
+
def self.included(base)
|
9
8
|
base.extend(ClassMethods)
|
9
|
+
|
10
10
|
base.class_eval do
|
11
11
|
alias_method :perform_action_without_benchmark, :perform_action
|
12
12
|
alias_method :perform_action, :perform_action_with_benchmark
|
@@ -43,14 +43,14 @@ module ActionController #:nodoc:
|
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
46
|
-
def render_with_benchmark(options = nil, deprecated_status = nil)
|
46
|
+
def render_with_benchmark(options = nil, deprecated_status = nil, &block)
|
47
47
|
unless logger
|
48
|
-
render_without_benchmark(options, deprecated_status)
|
48
|
+
render_without_benchmark(options, deprecated_status, &block)
|
49
49
|
else
|
50
50
|
db_runtime = ActiveRecord::Base.connection.reset_runtime if Object.const_defined?("ActiveRecord") && ActiveRecord::Base.connected?
|
51
51
|
|
52
52
|
render_output = nil
|
53
|
-
@rendering_runtime = Benchmark::measure{ render_output = render_without_benchmark(options, deprecated_status) }.real
|
53
|
+
@rendering_runtime = Benchmark::measure{ render_output = render_without_benchmark(options, deprecated_status, &block) }.real
|
54
54
|
|
55
55
|
if Object.const_defined?("ActiveRecord") && ActiveRecord::Base.connected?
|
56
56
|
@db_rt_before_render = db_runtime
|
@@ -8,16 +8,16 @@ module ActionController #:nodoc:
|
|
8
8
|
#
|
9
9
|
# Note: To turn off all caching and sweeping, set Base.perform_caching = false.
|
10
10
|
module Caching
|
11
|
-
def self.
|
12
|
-
super
|
11
|
+
def self.included(base) #:nodoc:
|
13
12
|
base.send(:include, Pages, Actions, Fragments, Sweeping)
|
13
|
+
|
14
14
|
base.class_eval do
|
15
15
|
@@perform_caching = true
|
16
16
|
cattr_accessor :perform_caching
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
-
# Page caching is an approach to caching where the entire action output of is stored as a HTML file that the web server
|
20
|
+
# Page caching is an approach to caching where the entire action output of is stored as a HTML file that the web server
|
21
21
|
# can serve without going through the Action Pack. This can be as much as 100 times faster than going through the process of dynamically
|
22
22
|
# generating the content. Unfortunately, this incredible speed-up is only available to stateless pages where all visitors
|
23
23
|
# are treated the same. Content management systems -- including weblogs and wikis -- have many pages that are a great fit
|
@@ -78,7 +78,7 @@ module ActionController #:nodoc:
|
|
78
78
|
File.delete(page_cache_path(path)) if File.exists?(page_cache_path(path))
|
79
79
|
end
|
80
80
|
end
|
81
|
-
|
81
|
+
|
82
82
|
# Manually cache the +content+ in the key determined by +path+. Example:
|
83
83
|
# cache_page "I'm the cached content", "/lists/show"
|
84
84
|
def cache_page(content, path)
|
@@ -94,18 +94,18 @@ module ActionController #:nodoc:
|
|
94
94
|
# matches the triggering url.
|
95
95
|
def caches_page(*actions)
|
96
96
|
return unless perform_caching
|
97
|
-
actions.each do |action|
|
97
|
+
actions.each do |action|
|
98
98
|
class_eval "after_filter { |c| c.cache_page if c.action_name == '#{action}' }"
|
99
99
|
end
|
100
100
|
end
|
101
|
-
|
101
|
+
|
102
102
|
private
|
103
103
|
def page_cache_file(path)
|
104
104
|
name = ((path.empty? || path == "/") ? "/index" : URI.unescape(path))
|
105
105
|
name << page_cache_extension unless (name.split('/').last || name).include? '.'
|
106
106
|
return name
|
107
107
|
end
|
108
|
-
|
108
|
+
|
109
109
|
def page_cache_path(path)
|
110
110
|
page_cache_directory + page_cache_file(path)
|
111
111
|
end
|
@@ -134,11 +134,11 @@ module ActionController #:nodoc:
|
|
134
134
|
|
135
135
|
private
|
136
136
|
def caching_allowed
|
137
|
-
!@request.post?
|
137
|
+
!@request.post? && @response.headers['Status'] && @response.headers['Status'].to_i < 400
|
138
138
|
end
|
139
139
|
end
|
140
140
|
|
141
|
-
# Action caching is similar to page caching by the fact that the entire output of the response is cached, but unlike page caching,
|
141
|
+
# Action caching is similar to page caching by the fact that the entire output of the response is cached, but unlike page caching,
|
142
142
|
# every request still goes through the Action Pack. The key benefit of this is that filters are run before the cache is served, which
|
143
143
|
# allows for authentication and other restrictions on whether someone is allowed to see the cache. Example:
|
144
144
|
#
|
@@ -184,7 +184,7 @@ module ActionController #:nodoc:
|
|
184
184
|
def initialize(*actions)
|
185
185
|
@actions = actions
|
186
186
|
end
|
187
|
-
|
187
|
+
|
188
188
|
def before(controller)
|
189
189
|
return unless @actions.include?(controller.action_name.intern)
|
190
190
|
if cache = controller.read_fragment(controller.url_for.split("://").last)
|
@@ -193,7 +193,7 @@ module ActionController #:nodoc:
|
|
193
193
|
false
|
194
194
|
end
|
195
195
|
end
|
196
|
-
|
196
|
+
|
197
197
|
def after(controller)
|
198
198
|
return if !@actions.include?(controller.action_name.intern) || controller.rendered_action_cache
|
199
199
|
controller.write_fragment(controller.url_for.split("://").last, controller.response.body)
|
@@ -211,7 +211,7 @@ module ActionController #:nodoc:
|
|
211
211
|
# <%= render_collection_of_partials "topic", Topic.find_all %>
|
212
212
|
# <% end %>
|
213
213
|
#
|
214
|
-
# This cache will bind to the name of action that called it. So you would be able to invalidate it using
|
214
|
+
# This cache will bind to the name of action that called it. So you would be able to invalidate it using
|
215
215
|
# <tt>expire_fragment(:controller => "topics", :action => "list")</tt> -- if that was the controller/action used. This is not too helpful
|
216
216
|
# if you need to cache multiple fragments per action or if the action itself is cached using <tt>caches_action</tt>. So instead we should
|
217
217
|
# qualify the name of the action used with something like:
|
@@ -272,7 +272,7 @@ module ActionController #:nodoc:
|
|
272
272
|
# Called by CacheHelper#cache
|
273
273
|
def cache_erb_fragment(block, name = {}, options = nil)
|
274
274
|
unless perform_caching then block.call; return end
|
275
|
-
|
275
|
+
|
276
276
|
buffer = eval("_erbout", block.binding)
|
277
277
|
|
278
278
|
if cache = read_fragment(name, options)
|
@@ -283,7 +283,7 @@ module ActionController #:nodoc:
|
|
283
283
|
write_fragment(name, buffer[pos..-1], options)
|
284
284
|
end
|
285
285
|
end
|
286
|
-
|
286
|
+
|
287
287
|
def write_fragment(name, content, options = nil)
|
288
288
|
return unless perform_caching
|
289
289
|
|
@@ -293,7 +293,7 @@ module ActionController #:nodoc:
|
|
293
293
|
end
|
294
294
|
content
|
295
295
|
end
|
296
|
-
|
296
|
+
|
297
297
|
def read_fragment(name, options = nil)
|
298
298
|
return unless perform_caching
|
299
299
|
|
@@ -302,11 +302,11 @@ module ActionController #:nodoc:
|
|
302
302
|
fragment_cache_store.read(key, options)
|
303
303
|
end
|
304
304
|
end
|
305
|
-
|
305
|
+
|
306
306
|
# Name can take one of three forms:
|
307
307
|
# * String: This would normally take the form of a path like "pages/45/notes"
|
308
308
|
# * Hash: Is treated as an implicit call to url_for, like { :controller => "pages", :action => "notes", :id => 45 }
|
309
|
-
# * Regexp: Will destroy all the matched fragments, example: %r{pages/\d*/notes}
|
309
|
+
# * Regexp: Will destroy all the matched fragments, example: %r{pages/\d*/notes} Ensure you do not specify start and finish in the regex (^$) because the actual filename matched looks like ./cache/filename/path.cache
|
310
310
|
def expire_fragment(name, options = nil)
|
311
311
|
return unless perform_caching
|
312
312
|
|
@@ -355,15 +355,15 @@ module ActionController #:nodoc:
|
|
355
355
|
def read(name, options=nil) #:nodoc:
|
356
356
|
@mutex.synchronize { super }
|
357
357
|
end
|
358
|
-
|
358
|
+
|
359
359
|
def write(name, value, options=nil) #:nodoc:
|
360
360
|
@mutex.synchronize { super }
|
361
361
|
end
|
362
|
-
|
362
|
+
|
363
363
|
def delete(name, options=nil) #:nodoc:
|
364
364
|
@mutex.synchronize { super }
|
365
365
|
end
|
366
|
-
|
366
|
+
|
367
367
|
def delete_matched(matcher, options=nil) #:nodoc:
|
368
368
|
@mutex.synchronize { super }
|
369
369
|
end
|
@@ -386,26 +386,28 @@ module ActionController #:nodoc:
|
|
386
386
|
super()
|
387
387
|
@address = address
|
388
388
|
@data = DRbObject.new(nil, address)
|
389
|
-
end
|
389
|
+
end
|
390
390
|
end
|
391
391
|
|
392
392
|
class MemCacheStore < MemoryStore #:nodoc:
|
393
|
-
attr_reader :
|
393
|
+
attr_reader :addresses
|
394
394
|
|
395
|
-
def initialize(
|
395
|
+
def initialize(*addresses)
|
396
396
|
super()
|
397
|
-
|
398
|
-
|
399
|
-
|
397
|
+
addresses = addresses.flatten
|
398
|
+
addresses = ["localhost"] if addresses.empty?
|
399
|
+
@addresses = addresses
|
400
|
+
@data = MemCache.new(*addresses)
|
401
|
+
end
|
400
402
|
end
|
401
403
|
|
402
404
|
class UnthreadedFileStore #:nodoc:
|
403
405
|
attr_reader :cache_path
|
404
|
-
|
406
|
+
|
405
407
|
def initialize(cache_path)
|
406
408
|
@cache_path = cache_path
|
407
409
|
end
|
408
|
-
|
410
|
+
|
409
411
|
def write(name, value, options = nil) #:nodoc:
|
410
412
|
ensure_cache_path(File.dirname(real_file_path(name)))
|
411
413
|
File.open(real_file_path(name), "wb+") { |f| f.write(value) }
|
@@ -426,7 +428,7 @@ module ActionController #:nodoc:
|
|
426
428
|
def delete_matched(matcher, options) #:nodoc:
|
427
429
|
search_dir(@cache_path) do |f|
|
428
430
|
if f =~ matcher
|
429
|
-
begin
|
431
|
+
begin
|
430
432
|
File.delete(f)
|
431
433
|
rescue Object => e
|
432
434
|
# If there's no cache, then there's nothing to complain about
|
@@ -434,12 +436,12 @@ module ActionController #:nodoc:
|
|
434
436
|
end
|
435
437
|
end
|
436
438
|
end
|
437
|
-
|
439
|
+
|
438
440
|
private
|
439
441
|
def real_file_path(name)
|
440
442
|
'%s/%s.cache' % [@cache_path, name.gsub('?', '.').gsub(':', '.')]
|
441
443
|
end
|
442
|
-
|
444
|
+
|
443
445
|
def ensure_cache_path(path)
|
444
446
|
FileUtils.makedirs(path) unless File.exists?(path)
|
445
447
|
end
|
@@ -470,10 +472,10 @@ module ActionController #:nodoc:
|
|
470
472
|
|
471
473
|
# Sweepers are the terminators of the caching world and responsible for expiring caches when model objects change.
|
472
474
|
# They do this by being half-observers, half-filters and implementing callbacks for both roles. A Sweeper example:
|
473
|
-
#
|
475
|
+
#
|
474
476
|
# class ListSweeper < ActionController::Caching::Sweeper
|
475
477
|
# observe List, Item
|
476
|
-
#
|
478
|
+
#
|
477
479
|
# def after_save(record)
|
478
480
|
# list = record.is_a?(List) ? record : record.list
|
479
481
|
# expire_page(:controller => "lists", :action => %w( show public feed ), :id => list.id)
|
@@ -518,6 +520,10 @@ module ActionController #:nodoc:
|
|
518
520
|
if defined?(ActiveRecord) and defined?(ActiveRecord::Observer)
|
519
521
|
class Sweeper < ActiveRecord::Observer #:nodoc:
|
520
522
|
attr_accessor :controller
|
523
|
+
|
524
|
+
# ActiveRecord::Observer will mark this class as reloadable even though it should not be.
|
525
|
+
# However, subclasses of ActionController::Caching::Sweeper should be Reloadable
|
526
|
+
include Reloadable::Subclasses
|
521
527
|
|
522
528
|
def before(controller)
|
523
529
|
self.controller = controller
|
@@ -526,17 +532,19 @@ module ActionController #:nodoc:
|
|
526
532
|
|
527
533
|
def after(controller)
|
528
534
|
callback(:after)
|
535
|
+
# Clean up, so that the controller can be collected after this request
|
536
|
+
self.controller = nil
|
529
537
|
end
|
530
|
-
|
538
|
+
|
531
539
|
private
|
532
540
|
def callback(timing)
|
533
541
|
controller_callback_method_name = "#{timing}_#{controller.controller_name.underscore}"
|
534
542
|
action_callback_method_name = "#{controller_callback_method_name}_#{controller.action_name}"
|
535
|
-
|
543
|
+
|
536
544
|
send(controller_callback_method_name) if respond_to?(controller_callback_method_name)
|
537
545
|
send(action_callback_method_name) if respond_to?(action_callback_method_name)
|
538
546
|
end
|
539
|
-
|
547
|
+
|
540
548
|
def method_missing(method, *arguments)
|
541
549
|
return if @controller.nil?
|
542
550
|
@controller.send(method, *arguments)
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'cgi'
|
2
2
|
require 'action_controller/vendor/xml_simple'
|
3
|
+
require 'action_controller/vendor/xml_node'
|
3
4
|
|
4
5
|
# Static methods for parsing the query and request parameters that can be used in
|
5
6
|
# a CGI extension class or testing in isolation.
|
@@ -57,20 +58,84 @@ class CGIMethods #:nodoc:
|
|
57
58
|
parsed_params
|
58
59
|
end
|
59
60
|
|
60
|
-
def self.parse_formatted_request_parameters(
|
61
|
-
case
|
62
|
-
when
|
63
|
-
|
61
|
+
def self.parse_formatted_request_parameters(mime_type, raw_post_data)
|
62
|
+
params = case strategy = ActionController::Base.param_parsers[mime_type]
|
63
|
+
when Proc
|
64
|
+
strategy.call(raw_post_data)
|
65
|
+
when :xml_simple
|
66
|
+
raw_post_data.blank? ? nil :
|
67
|
+
typecast_xml_value(XmlSimple.xml_in(raw_post_data,
|
68
|
+
'forcearray' => false,
|
69
|
+
'forcecontent' => true,
|
70
|
+
'keeproot' => true,
|
71
|
+
'contentkey' => '__content__'))
|
64
72
|
when :yaml
|
65
|
-
|
73
|
+
YAML.load(raw_post_data)
|
74
|
+
when :xml_node
|
75
|
+
node = XmlNode.from_xml(raw_post_data)
|
76
|
+
{ node.node_name => node }
|
66
77
|
end
|
78
|
+
|
79
|
+
dasherize_keys(params || {})
|
67
80
|
rescue Object => e
|
68
81
|
{ "exception" => "#{e.message} (#{e.class})", "backtrace" => e.backtrace,
|
69
|
-
"raw_post_data" => raw_post_data, "format" =>
|
82
|
+
"raw_post_data" => raw_post_data, "format" => mime_type }
|
83
|
+
end
|
84
|
+
|
85
|
+
def self.typecast_xml_value(value)
|
86
|
+
case value
|
87
|
+
when Hash
|
88
|
+
if value.has_key?("__content__")
|
89
|
+
content = translate_xml_entities(value["__content__"])
|
90
|
+
case value["type"]
|
91
|
+
when "integer" then content.to_i
|
92
|
+
when "boolean" then content == "true"
|
93
|
+
when "datetime" then Time.parse(content)
|
94
|
+
when "date" then Date.parse(content)
|
95
|
+
else content
|
96
|
+
end
|
97
|
+
else
|
98
|
+
value.empty? ? nil : value.inject({}) do |h,(k,v)|
|
99
|
+
h[k] = typecast_xml_value(v)
|
100
|
+
h
|
101
|
+
end
|
102
|
+
end
|
103
|
+
when Array
|
104
|
+
value.map! { |i| typecast_xml_value(i) }
|
105
|
+
case value.length
|
106
|
+
when 0 then nil
|
107
|
+
when 1 then value.first
|
108
|
+
else value
|
109
|
+
end
|
110
|
+
else
|
111
|
+
raise "can't typecast #{value.inspect}"
|
112
|
+
end
|
70
113
|
end
|
71
114
|
|
72
115
|
private
|
73
116
|
|
117
|
+
def self.translate_xml_entities(value)
|
118
|
+
value.gsub(/</, "<").
|
119
|
+
gsub(/>/, ">").
|
120
|
+
gsub(/"/, '"').
|
121
|
+
gsub(/'/, "'").
|
122
|
+
gsub(/&/, "&")
|
123
|
+
end
|
124
|
+
|
125
|
+
def self.dasherize_keys(params)
|
126
|
+
case params.class.to_s
|
127
|
+
when "Hash"
|
128
|
+
params.inject({}) do |h,(k,v)|
|
129
|
+
h[k.to_s.tr("-", "_")] = dasherize_keys(v)
|
130
|
+
h
|
131
|
+
end
|
132
|
+
when "Array"
|
133
|
+
params.map { |v| dasherize_keys(v) }
|
134
|
+
else
|
135
|
+
params
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
74
139
|
# Splits the given key into several pieces. Example keys are 'name', 'person[name]',
|
75
140
|
# 'person[name][first]', and 'people[]'. In each instance, an Array instance is returned.
|
76
141
|
# 'person[name][first]' produces ['person', 'name', 'first']; 'people[]' produces ['people', '']
|
@@ -108,7 +108,7 @@ class CGI #:nodoc:
|
|
108
108
|
cookies = Hash.new([])
|
109
109
|
|
110
110
|
if raw_cookie
|
111
|
-
raw_cookie.split(/;
|
111
|
+
raw_cookie.split(/; ?/).each do |pairs|
|
112
112
|
name, values = pairs.split('=',2)
|
113
113
|
next unless name and values
|
114
114
|
name = CGI::unescape(name)
|
@@ -36,25 +36,26 @@ module ActionController #:nodoc:
|
|
36
36
|
|
37
37
|
DEFAULT_SESSION_OPTIONS = {
|
38
38
|
:database_manager => CGI::Session::PStore,
|
39
|
-
:prefix
|
40
|
-
:session_path
|
39
|
+
:prefix => "ruby_sess.",
|
40
|
+
:session_path => "/"
|
41
41
|
} unless const_defined?(:DEFAULT_SESSION_OPTIONS)
|
42
42
|
|
43
43
|
def initialize(cgi, session_options = {})
|
44
44
|
@cgi = cgi
|
45
45
|
@session_options = session_options
|
46
|
+
@env = @cgi.send(:env_table)
|
46
47
|
super()
|
47
48
|
end
|
48
49
|
|
49
50
|
def query_string
|
50
51
|
if (qs = @cgi.query_string) && !qs.empty?
|
51
52
|
qs
|
52
|
-
elsif uri = env['REQUEST_URI']
|
53
|
+
elsif uri = @env['REQUEST_URI']
|
53
54
|
parts = uri.split('?')
|
54
55
|
parts.shift
|
55
56
|
parts.join('?')
|
56
57
|
else
|
57
|
-
env['QUERY_STRING'] || ''
|
58
|
+
@env['QUERY_STRING'] || ''
|
58
59
|
end
|
59
60
|
end
|
60
61
|
|
@@ -63,31 +64,39 @@ module ActionController #:nodoc:
|
|
63
64
|
end
|
64
65
|
|
65
66
|
def request_parameters
|
66
|
-
if
|
67
|
-
CGIMethods.parse_formatted_request_parameters(
|
67
|
+
if ActionController::Base.param_parsers.has_key?(content_type)
|
68
|
+
CGIMethods.parse_formatted_request_parameters(content_type, @env['RAW_POST_DATA'])
|
68
69
|
else
|
69
70
|
CGIMethods.parse_request_parameters(@cgi.params)
|
70
71
|
end
|
71
72
|
end
|
72
|
-
|
73
|
-
def env
|
74
|
-
@cgi.send(:env_table)
|
75
|
-
end
|
76
|
-
|
73
|
+
|
77
74
|
def cookies
|
78
75
|
@cgi.cookies.freeze
|
79
76
|
end
|
80
77
|
|
78
|
+
def host_with_port
|
79
|
+
if forwarded = env["HTTP_X_FORWARDED_HOST"]
|
80
|
+
forwarded.split(/,\s?/).last
|
81
|
+
elsif http_host = env['HTTP_HOST']
|
82
|
+
http_host
|
83
|
+
elsif server_name = env['SERVER_NAME']
|
84
|
+
server_name
|
85
|
+
else
|
86
|
+
"#{env['SERVER_ADDR']}:#{env['SERVER_PORT']}"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
81
90
|
def host
|
82
|
-
|
91
|
+
host_with_port[/^[^:]+/]
|
83
92
|
end
|
84
|
-
|
93
|
+
|
85
94
|
def port
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
95
|
+
if host_with_port =~ /:(\d+)$/
|
96
|
+
$1.to_i
|
97
|
+
else
|
98
|
+
standard_port
|
99
|
+
end
|
91
100
|
end
|
92
101
|
|
93
102
|
def session
|
@@ -136,7 +145,7 @@ module ActionController #:nodoc:
|
|
136
145
|
Module.const_missing($1)
|
137
146
|
rescue LoadError, NameError => const_error
|
138
147
|
raise ActionController::SessionRestoreError, <<end_msg
|
139
|
-
Session contains objects whose class definition isn't available.
|
148
|
+
Session contains objects whose class definition isn\'t available.
|
140
149
|
Remember to require the classes for all objects kept in the session.
|
141
150
|
(Original exception: #{const_error.message} [#{const_error.class}])
|
142
151
|
end_msg
|
@@ -183,11 +192,14 @@ end_msg
|
|
183
192
|
|
184
193
|
private
|
185
194
|
def convert_content_type!(headers)
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
195
|
+
if header = headers.delete("Content-Type")
|
196
|
+
headers["type"] = header
|
197
|
+
end
|
198
|
+
if header = headers.delete("Content-type")
|
199
|
+
headers["type"] = header
|
200
|
+
end
|
201
|
+
if header = headers.delete("content-type")
|
202
|
+
headers["type"] = header
|
191
203
|
end
|
192
204
|
end
|
193
205
|
end
|