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.
- data/CHANGELOG +433 -375
- data/MIT-LICENSE +1 -1
- data/README +21 -75
- data/Rakefile +1 -1
- data/lib/action_controller.rb +80 -43
- data/lib/action_controller/assertions/model_assertions.rb +1 -0
- data/lib/action_controller/assertions/response_assertions.rb +43 -16
- data/lib/action_controller/assertions/routing_assertions.rb +1 -1
- data/lib/action_controller/assertions/selector_assertions.rb +17 -12
- data/lib/action_controller/assertions/tag_assertions.rb +1 -4
- data/lib/action_controller/base.rb +153 -82
- data/lib/action_controller/benchmarking.rb +9 -9
- data/lib/action_controller/caching.rb +9 -11
- data/lib/action_controller/caching/actions.rb +11 -18
- data/lib/action_controller/caching/fragments.rb +28 -20
- data/lib/action_controller/caching/pages.rb +13 -15
- data/lib/action_controller/caching/sweeping.rb +2 -2
- data/lib/action_controller/cgi_ext.rb +0 -1
- data/lib/action_controller/cgi_ext/cookie.rb +2 -0
- data/lib/action_controller/cgi_process.rb +54 -162
- data/lib/action_controller/cookies.rb +13 -25
- data/lib/action_controller/dispatcher.rb +43 -122
- data/lib/action_controller/failsafe.rb +52 -0
- data/lib/action_controller/flash.rb +38 -47
- data/lib/action_controller/helpers.rb +13 -9
- data/lib/action_controller/http_authentication.rb +203 -23
- data/lib/action_controller/integration.rb +126 -70
- data/lib/action_controller/layout.rb +36 -39
- data/lib/action_controller/middleware_stack.rb +119 -0
- data/lib/action_controller/middlewares.rb +13 -0
- data/lib/action_controller/mime_responds.rb +19 -4
- data/lib/action_controller/mime_type.rb +8 -0
- data/lib/action_controller/params_parser.rb +71 -0
- data/lib/action_controller/performance_test.rb +0 -1
- data/lib/action_controller/polymorphic_routes.rb +36 -30
- data/lib/action_controller/reloader.rb +14 -0
- data/lib/action_controller/request.rb +107 -499
- data/lib/action_controller/request_forgery_protection.rb +7 -39
- data/lib/action_controller/rescue.rb +55 -35
- data/lib/action_controller/resources.rb +34 -31
- data/lib/action_controller/response.rb +99 -57
- data/lib/action_controller/rewindable_input.rb +28 -0
- data/lib/action_controller/routing.rb +7 -7
- data/lib/action_controller/routing/builder.rb +4 -1
- data/lib/action_controller/routing/optimisations.rb +1 -1
- data/lib/action_controller/routing/recognition_optimisation.rb +1 -2
- data/lib/action_controller/routing/route.rb +15 -5
- data/lib/action_controller/routing/route_set.rb +82 -35
- data/lib/action_controller/routing/segments.rb +35 -0
- data/lib/action_controller/session/abstract_store.rb +181 -0
- data/lib/action_controller/session/cookie_store.rb +197 -175
- data/lib/action_controller/session/mem_cache_store.rb +36 -83
- data/lib/action_controller/session_management.rb +26 -134
- data/lib/action_controller/streaming.rb +24 -7
- data/lib/action_controller/templates/rescues/diagnostics.erb +2 -2
- data/lib/action_controller/templates/rescues/template_error.erb +2 -2
- data/lib/action_controller/test_case.rb +87 -30
- data/lib/action_controller/test_process.rb +145 -104
- data/lib/action_controller/uploaded_file.rb +44 -0
- data/lib/action_controller/url_rewriter.rb +3 -6
- data/lib/action_controller/vendor/html-scanner.rb +16 -0
- data/lib/action_controller/vendor/html-scanner/html/selector.rb +1 -1
- data/lib/action_controller/vendor/rack-1.0/rack.rb +89 -0
- data/lib/action_controller/vendor/rack-1.0/rack/adapter/camping.rb +22 -0
- data/lib/action_controller/vendor/rack-1.0/rack/auth/abstract/handler.rb +37 -0
- data/lib/action_controller/vendor/rack-1.0/rack/auth/abstract/request.rb +37 -0
- data/lib/action_controller/vendor/rack-1.0/rack/auth/basic.rb +58 -0
- data/lib/action_controller/vendor/rack-1.0/rack/auth/digest/md5.rb +124 -0
- data/lib/action_controller/vendor/rack-1.0/rack/auth/digest/nonce.rb +51 -0
- data/lib/action_controller/vendor/rack-1.0/rack/auth/digest/params.rb +55 -0
- data/lib/action_controller/vendor/rack-1.0/rack/auth/digest/request.rb +40 -0
- data/lib/action_controller/vendor/rack-1.0/rack/auth/openid.rb +480 -0
- data/lib/action_controller/vendor/rack-1.0/rack/builder.rb +63 -0
- data/lib/action_controller/vendor/rack-1.0/rack/cascade.rb +36 -0
- data/lib/action_controller/vendor/rack-1.0/rack/chunked.rb +49 -0
- data/lib/action_controller/vendor/rack-1.0/rack/commonlogger.rb +61 -0
- data/lib/action_controller/vendor/rack-1.0/rack/conditionalget.rb +45 -0
- data/lib/action_controller/vendor/rack-1.0/rack/content_length.rb +29 -0
- data/lib/action_controller/vendor/rack-1.0/rack/content_type.rb +23 -0
- data/lib/action_controller/vendor/rack-1.0/rack/deflater.rb +85 -0
- data/lib/action_controller/vendor/rack-1.0/rack/directory.rb +153 -0
- data/lib/action_controller/vendor/rack-1.0/rack/file.rb +88 -0
- data/lib/action_controller/vendor/rack-1.0/rack/handler.rb +48 -0
- data/lib/action_controller/vendor/rack-1.0/rack/handler/cgi.rb +61 -0
- data/lib/action_controller/vendor/rack-1.0/rack/handler/evented_mongrel.rb +8 -0
- data/lib/action_controller/vendor/rack-1.0/rack/handler/fastcgi.rb +89 -0
- data/lib/action_controller/vendor/rack-1.0/rack/handler/lsws.rb +55 -0
- data/lib/action_controller/vendor/rack-1.0/rack/handler/mongrel.rb +84 -0
- data/lib/action_controller/vendor/rack-1.0/rack/handler/scgi.rb +59 -0
- data/lib/action_controller/vendor/rack-1.0/rack/handler/swiftiplied_mongrel.rb +8 -0
- data/lib/action_controller/vendor/rack-1.0/rack/handler/thin.rb +18 -0
- data/lib/action_controller/vendor/rack-1.0/rack/handler/webrick.rb +67 -0
- data/lib/action_controller/vendor/rack-1.0/rack/head.rb +19 -0
- data/lib/action_controller/vendor/rack-1.0/rack/lint.rb +462 -0
- data/lib/action_controller/vendor/rack-1.0/rack/lobster.rb +65 -0
- data/lib/action_controller/vendor/rack-1.0/rack/lock.rb +16 -0
- data/lib/action_controller/vendor/rack-1.0/rack/methodoverride.rb +27 -0
- data/lib/action_controller/vendor/rack-1.0/rack/mime.rb +204 -0
- data/lib/action_controller/vendor/rack-1.0/rack/mock.rb +160 -0
- data/lib/action_controller/vendor/rack-1.0/rack/recursive.rb +57 -0
- data/lib/action_controller/vendor/rack-1.0/rack/reloader.rb +64 -0
- data/lib/action_controller/vendor/rack-1.0/rack/request.rb +241 -0
- data/lib/action_controller/vendor/rack-1.0/rack/response.rb +179 -0
- data/lib/action_controller/vendor/rack-1.0/rack/session/abstract/id.rb +142 -0
- data/lib/action_controller/vendor/rack-1.0/rack/session/cookie.rb +91 -0
- data/lib/action_controller/vendor/rack-1.0/rack/session/memcache.rb +109 -0
- data/lib/action_controller/vendor/rack-1.0/rack/session/pool.rb +100 -0
- data/lib/action_controller/vendor/rack-1.0/rack/showexceptions.rb +349 -0
- data/lib/action_controller/vendor/rack-1.0/rack/showstatus.rb +106 -0
- data/lib/action_controller/vendor/rack-1.0/rack/static.rb +38 -0
- data/lib/action_controller/vendor/rack-1.0/rack/urlmap.rb +55 -0
- data/lib/action_controller/vendor/rack-1.0/rack/utils.rb +392 -0
- data/lib/action_controller/verification.rb +1 -1
- data/lib/action_pack.rb +1 -1
- data/lib/action_pack/version.rb +2 -2
- data/lib/action_view.rb +22 -17
- data/lib/action_view/base.rb +53 -79
- data/lib/action_view/erb/util.rb +38 -0
- data/lib/action_view/helpers.rb +24 -5
- data/lib/action_view/helpers/active_record_helper.rb +2 -2
- data/lib/action_view/helpers/asset_tag_helper.rb +81 -50
- data/lib/action_view/helpers/atom_feed_helper.rb +1 -1
- data/lib/action_view/helpers/benchmark_helper.rb +26 -5
- data/lib/action_view/helpers/date_helper.rb +82 -7
- data/lib/action_view/helpers/form_helper.rb +295 -64
- data/lib/action_view/helpers/form_options_helper.rb +160 -18
- data/lib/action_view/helpers/form_tag_helper.rb +2 -2
- data/lib/action_view/helpers/number_helper.rb +31 -18
- data/lib/action_view/helpers/prototype_helper.rb +2 -12
- data/lib/action_view/helpers/sanitize_helper.rb +0 -10
- data/lib/action_view/helpers/scriptaculous_helper.rb +1 -0
- data/lib/action_view/helpers/tag_helper.rb +3 -4
- data/lib/action_view/helpers/text_helper.rb +99 -122
- data/lib/action_view/helpers/translation_helper.rb +19 -1
- data/lib/action_view/helpers/url_helper.rb +25 -2
- data/lib/action_view/inline_template.rb +1 -1
- data/lib/action_view/locale/en.yml +19 -1
- data/lib/action_view/partials.rb +46 -9
- data/lib/action_view/paths.rb +28 -84
- data/lib/action_view/reloadable_template.rb +117 -0
- data/lib/action_view/renderable.rb +28 -35
- data/lib/action_view/renderable_partial.rb +3 -4
- data/lib/action_view/template.rb +172 -31
- data/lib/action_view/template_error.rb +8 -9
- data/lib/action_view/template_handler.rb +1 -1
- data/lib/action_view/template_handlers.rb +9 -6
- data/lib/action_view/template_handlers/erb.rb +2 -39
- data/lib/action_view/template_handlers/rjs.rb +1 -0
- data/lib/action_view/test_case.rb +27 -1
- data/test/abstract_unit.rb +23 -17
- data/test/active_record_unit.rb +5 -4
- data/test/activerecord/active_record_store_test.rb +139 -106
- data/test/activerecord/render_partial_with_record_identification_test.rb +5 -21
- data/test/controller/action_pack_assertions_test.rb +25 -23
- data/test/controller/addresses_render_test.rb +3 -6
- data/test/controller/assert_select_test.rb +83 -70
- data/test/controller/base_test.rb +11 -13
- data/test/controller/benchmark_test.rb +3 -3
- data/test/controller/caching_test.rb +34 -24
- data/test/controller/capture_test.rb +3 -6
- data/test/controller/content_type_test.rb +3 -6
- data/test/controller/cookie_test.rb +31 -66
- data/test/controller/deprecation/deprecated_base_methods_test.rb +9 -11
- data/test/controller/dispatcher_test.rb +23 -28
- data/test/controller/fake_models.rb +8 -0
- data/test/controller/filters_test.rb +6 -2
- data/test/controller/flash_test.rb +2 -6
- data/test/controller/helper_test.rb +15 -1
- data/test/controller/html-scanner/document_test.rb +1 -1
- data/test/controller/html-scanner/sanitizer_test.rb +1 -1
- data/test/controller/http_basic_authentication_test.rb +88 -0
- data/test/controller/http_digest_authentication_test.rb +178 -0
- data/test/controller/integration_test.rb +56 -52
- data/test/controller/layout_test.rb +46 -44
- data/test/controller/middleware_stack_test.rb +90 -0
- data/test/controller/mime_responds_test.rb +7 -11
- data/test/controller/mime_type_test.rb +9 -0
- data/test/controller/polymorphic_routes_test.rb +235 -151
- data/test/controller/rack_test.rb +52 -81
- data/test/controller/redirect_test.rb +6 -14
- data/test/controller/render_test.rb +273 -60
- data/test/controller/request/json_params_parsing_test.rb +45 -0
- data/test/controller/request/multipart_params_parsing_test.rb +223 -0
- data/test/controller/request/query_string_parsing_test.rb +120 -0
- data/test/controller/request/url_encoded_params_parsing_test.rb +184 -0
- data/test/controller/request/xml_params_parsing_test.rb +88 -0
- data/test/controller/request_forgery_protection_test.rb +17 -98
- data/test/controller/request_test.rb +45 -530
- data/test/controller/rescue_test.rb +45 -22
- data/test/controller/resources_test.rb +112 -37
- data/test/controller/routing_test.rb +1442 -1384
- data/test/controller/selector_test.rb +3 -3
- data/test/controller/send_file_test.rb +30 -3
- data/test/controller/session/cookie_store_test.rb +169 -240
- data/test/controller/session/mem_cache_store_test.rb +94 -148
- data/test/controller/session/test_session_test.rb +58 -0
- data/test/controller/test_test.rb +32 -13
- data/test/controller/url_rewriter_test.rb +54 -4
- data/test/controller/verification_test.rb +1 -1
- data/test/controller/view_paths_test.rb +15 -15
- data/test/controller/webservice_test.rb +178 -147
- data/test/fixtures/alternate_helpers/foo_helper.rb +3 -0
- data/test/fixtures/layout_tests/alt/layouts/alt.rhtml +0 -0
- data/test/fixtures/layouts/default_html.html.erb +1 -0
- data/test/fixtures/layouts/xhr.html.erb +2 -0
- data/test/fixtures/multipart/empty +10 -0
- data/test/fixtures/multipart/hello.txt +1 -0
- data/test/fixtures/multipart/none +9 -0
- data/test/fixtures/public/500.da.html +1 -0
- data/test/fixtures/quiz/questions/_question.html.erb +1 -0
- data/test/fixtures/replies.yml +1 -1
- data/test/fixtures/test/_one.html.erb +1 -0
- data/test/fixtures/test/_two.html.erb +1 -0
- data/test/fixtures/test/dont_pick_me +1 -0
- data/test/fixtures/test/hello.builder +1 -1
- data/test/fixtures/test/hello_world.da.html.erb +1 -0
- data/test/fixtures/test/hello_world.erb~ +1 -0
- data/test/fixtures/test/hello_world.pt-BR.html.erb +1 -0
- data/test/fixtures/test/malformed/malformed.en.html.erb~ +1 -0
- data/test/fixtures/test/malformed/malformed.erb~ +1 -0
- data/test/fixtures/test/malformed/malformed.html.erb~ +1 -0
- data/test/fixtures/test/render_explicit_html_template.js.rjs +1 -0
- data/test/fixtures/test/render_implicit_html_template.js.rjs +1 -0
- data/test/fixtures/test/render_implicit_html_template_from_xhr_request.da.html.erb +1 -0
- data/test/fixtures/test/render_implicit_html_template_from_xhr_request.html.erb +1 -0
- data/test/fixtures/test/render_implicit_js_template_without_layout.js.erb +1 -0
- data/test/fixtures/test/utf8.html.erb +2 -0
- data/test/template/active_record_helper_i18n_test.rb +31 -33
- data/test/template/active_record_helper_test.rb +34 -0
- data/test/template/asset_tag_helper_test.rb +52 -14
- data/test/template/atom_feed_helper_test.rb +3 -5
- data/test/template/benchmark_helper_test.rb +50 -24
- data/test/template/compiled_templates_test.rb +177 -33
- data/test/template/date_helper_i18n_test.rb +88 -81
- data/test/template/date_helper_test.rb +427 -43
- data/test/template/form_helper_test.rb +243 -44
- data/test/template/form_options_helper_test.rb +631 -565
- data/test/template/form_tag_helper_test.rb +9 -2
- data/test/template/javascript_helper_test.rb +0 -5
- data/test/template/number_helper_i18n_test.rb +60 -48
- data/test/template/number_helper_test.rb +1 -0
- data/test/template/render_test.rb +117 -35
- data/test/template/test_test.rb +4 -6
- data/test/template/text_helper_test.rb +129 -50
- data/test/template/translation_helper_test.rb +23 -19
- data/test/template/url_helper_test.rb +35 -2
- data/test/view/test_case_test.rb +8 -0
- metadata +197 -23
- data/lib/action_controller/assertions.rb +0 -69
- data/lib/action_controller/caching/sql_cache.rb +0 -18
- data/lib/action_controller/cgi_ext/session.rb +0 -53
- data/lib/action_controller/components.rb +0 -169
- data/lib/action_controller/rack_process.rb +0 -297
- data/lib/action_controller/request_profiler.rb +0 -169
- data/lib/action_controller/session/active_record_store.rb +0 -340
- data/lib/action_controller/session/drb_server.rb +0 -32
- data/lib/action_controller/session/drb_store.rb +0 -35
- data/test/controller/cgi_test.rb +0 -269
- data/test/controller/components_test.rb +0 -156
- data/test/controller/http_authentication_test.rb +0 -54
- data/test/controller/integration_upload_test.rb +0 -43
- data/test/controller/session_fixation_test.rb +0 -89
- data/test/controller/session_management_test.rb +0 -178
- data/test/fixtures/test/hello_world.js +0 -1
@@ -23,8 +23,8 @@ module ActionController #:nodoc:
|
|
23
23
|
def benchmark(title, log_level = Logger::DEBUG, use_silence = true)
|
24
24
|
if logger && logger.level == log_level
|
25
25
|
result = nil
|
26
|
-
|
27
|
-
logger.add(log_level, "#{title} (#{('%.1f' %
|
26
|
+
ms = Benchmark.ms { result = use_silence ? silence { yield } : yield }
|
27
|
+
logger.add(log_level, "#{title} (#{('%.1f' % ms)}ms)")
|
28
28
|
result
|
29
29
|
else
|
30
30
|
yield
|
@@ -48,7 +48,7 @@ module ActionController #:nodoc:
|
|
48
48
|
end
|
49
49
|
|
50
50
|
render_output = nil
|
51
|
-
@view_runtime = Benchmark
|
51
|
+
@view_runtime = Benchmark.ms { render_output = render_without_benchmark(options, extra_options, &block) }
|
52
52
|
|
53
53
|
if Object.const_defined?("ActiveRecord") && ActiveRecord::Base.connected?
|
54
54
|
@db_rt_before_render = db_runtime
|
@@ -65,11 +65,11 @@ module ActionController #:nodoc:
|
|
65
65
|
private
|
66
66
|
def perform_action_with_benchmark
|
67
67
|
if logger
|
68
|
-
|
68
|
+
ms = [Benchmark.ms { perform_action_without_benchmark }, 0.01].max
|
69
69
|
logging_view = defined?(@view_runtime)
|
70
70
|
logging_active_record = Object.const_defined?("ActiveRecord") && ActiveRecord::Base.connected?
|
71
71
|
|
72
|
-
log_message =
|
72
|
+
log_message = 'Completed in %.0fms' % ms
|
73
73
|
|
74
74
|
if logging_view || logging_active_record
|
75
75
|
log_message << " ("
|
@@ -83,25 +83,25 @@ module ActionController #:nodoc:
|
|
83
83
|
end
|
84
84
|
end
|
85
85
|
|
86
|
-
log_message << " | #{
|
86
|
+
log_message << " | #{response.status}"
|
87
87
|
log_message << " [#{complete_request_uri rescue "unknown"}]"
|
88
88
|
|
89
89
|
logger.info(log_message)
|
90
|
-
response.headers["X-Runtime"] = "
|
90
|
+
response.headers["X-Runtime"] = "%.0f" % ms
|
91
91
|
else
|
92
92
|
perform_action_without_benchmark
|
93
93
|
end
|
94
94
|
end
|
95
95
|
|
96
96
|
def view_runtime
|
97
|
-
"View: %.0f" %
|
97
|
+
"View: %.0f" % @view_runtime
|
98
98
|
end
|
99
99
|
|
100
100
|
def active_record_runtime
|
101
101
|
db_runtime = ActiveRecord::Base.connection.reset_runtime
|
102
102
|
db_runtime += @db_rt_before_render if @db_rt_before_render
|
103
103
|
db_runtime += @db_rt_after_render if @db_rt_after_render
|
104
|
-
"DB: %.0f" %
|
104
|
+
"DB: %.0f" % db_runtime
|
105
105
|
end
|
106
106
|
end
|
107
107
|
end
|
@@ -2,13 +2,6 @@ require 'fileutils'
|
|
2
2
|
require 'uri'
|
3
3
|
require 'set'
|
4
4
|
|
5
|
-
require 'action_controller/caching/pages'
|
6
|
-
require 'action_controller/caching/actions'
|
7
|
-
require 'action_controller/caching/sql_cache'
|
8
|
-
require 'action_controller/caching/sweeping'
|
9
|
-
require 'action_controller/caching/fragments'
|
10
|
-
|
11
|
-
|
12
5
|
module ActionController #:nodoc:
|
13
6
|
# Caching is a cheap way of speeding up slow applications by keeping the result of calculations, renderings, and database calls
|
14
7
|
# around for subsequent requests. Action Controller affords you three approaches in varying levels of granularity: Page, Action, Fragment.
|
@@ -31,6 +24,12 @@ module ActionController #:nodoc:
|
|
31
24
|
# ActionController::Base.cache_store = :mem_cache_store, "localhost"
|
32
25
|
# ActionController::Base.cache_store = MyOwnStore.new("parameter")
|
33
26
|
module Caching
|
27
|
+
autoload :Actions, 'action_controller/caching/actions'
|
28
|
+
autoload :Fragments, 'action_controller/caching/fragments'
|
29
|
+
autoload :Pages, 'action_controller/caching/pages'
|
30
|
+
autoload :Sweeper, 'action_controller/caching/sweeping'
|
31
|
+
autoload :Sweeping, 'action_controller/caching/sweeping'
|
32
|
+
|
34
33
|
def self.included(base) #:nodoc:
|
35
34
|
base.class_eval do
|
36
35
|
@@cache_store = nil
|
@@ -42,7 +41,7 @@ module ActionController #:nodoc:
|
|
42
41
|
end
|
43
42
|
|
44
43
|
include Pages, Actions, Fragments
|
45
|
-
include Sweeping
|
44
|
+
include Sweeping if defined?(ActiveRecord)
|
46
45
|
|
47
46
|
@@perform_caching = true
|
48
47
|
cattr_accessor :perform_caching
|
@@ -63,10 +62,9 @@ module ActionController #:nodoc:
|
|
63
62
|
end
|
64
63
|
end
|
65
64
|
|
66
|
-
|
67
|
-
private
|
65
|
+
private
|
68
66
|
def cache_configured?
|
69
67
|
self.class.cache_configured?
|
70
68
|
end
|
71
69
|
end
|
72
|
-
end
|
70
|
+
end
|
@@ -113,7 +113,7 @@ module ActionController #:nodoc:
|
|
113
113
|
end
|
114
114
|
|
115
115
|
def caching_allowed(controller)
|
116
|
-
controller.request.get? && controller.response.
|
116
|
+
controller.request.get? && controller.response.status.to_i == 200
|
117
117
|
end
|
118
118
|
|
119
119
|
def cache_layout?
|
@@ -129,24 +129,23 @@ module ActionController #:nodoc:
|
|
129
129
|
attr_reader :path, :extension
|
130
130
|
|
131
131
|
class << self
|
132
|
-
def path_for(controller, options, infer_extension=true)
|
132
|
+
def path_for(controller, options, infer_extension = true)
|
133
133
|
new(controller, options, infer_extension).path
|
134
134
|
end
|
135
135
|
end
|
136
136
|
|
137
137
|
# When true, infer_extension will look up the cache path extension from the request's path & format.
|
138
|
-
# This is desirable when reading and writing the cache, but not when expiring the cache -
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
138
|
+
# This is desirable when reading and writing the cache, but not when expiring the cache -
|
139
|
+
# expire_action should expire the same files regardless of the request format.
|
140
|
+
def initialize(controller, options = {}, infer_extension = true)
|
141
|
+
if infer_extension
|
142
|
+
extract_extension(controller.request)
|
143
|
+
options = options.reverse_merge(:format => @extension) if options.is_a?(Hash)
|
143
144
|
end
|
145
|
+
|
144
146
|
path = controller.url_for(options).split('://').last
|
145
147
|
normalize!(path)
|
146
|
-
|
147
|
-
@extension = request_extension
|
148
|
-
add_extension!(path, @extension)
|
149
|
-
end
|
148
|
+
add_extension!(path, @extension)
|
150
149
|
@path = URI.unescape(path)
|
151
150
|
end
|
152
151
|
|
@@ -162,13 +161,7 @@ module ActionController #:nodoc:
|
|
162
161
|
def extract_extension(request)
|
163
162
|
# Don't want just what comes after the last '.' to accommodate multi part extensions
|
164
163
|
# such as tar.gz.
|
165
|
-
extension = request.path[/^[^.]+\.(.+)$/, 1]
|
166
|
-
|
167
|
-
# If there's no extension in the path, check request.format
|
168
|
-
if extension.nil?
|
169
|
-
extension = request.cache_format
|
170
|
-
end
|
171
|
-
extension
|
164
|
+
@extension = request.path[/^[^.]+\.(.+)$/, 1] || request.cache_format
|
172
165
|
end
|
173
166
|
end
|
174
167
|
end
|
@@ -10,23 +10,23 @@ module ActionController #:nodoc:
|
|
10
10
|
# <%= render :partial => "topic", :collection => Topic.find(:all) %>
|
11
11
|
# <% end %>
|
12
12
|
#
|
13
|
-
# This cache will bind to the name of the action that called it, so if this code was part of the view for the topics/list action, you would
|
14
|
-
# be able to invalidate it using <tt>expire_fragment(:controller => "topics", :action => "list")</tt>.
|
15
|
-
#
|
16
|
-
# This default behavior is of limited use if you need to cache multiple fragments per action or if the action itself is cached using
|
13
|
+
# This cache will bind to the name of the action that called it, so if this code was part of the view for the topics/list action, you would
|
14
|
+
# be able to invalidate it using <tt>expire_fragment(:controller => "topics", :action => "list")</tt>.
|
15
|
+
#
|
16
|
+
# This default behavior is of limited use if you need to cache multiple fragments per action or if the action itself is cached using
|
17
17
|
# <tt>caches_action</tt>, so we also have the option to qualify the name of the cached fragment with something like:
|
18
18
|
#
|
19
19
|
# <% cache(:action => "list", :action_suffix => "all_topics") do %>
|
20
20
|
#
|
21
|
-
# That would result in a name such as "/topics/list/all_topics", avoiding conflicts with the action cache and with any fragments that use a
|
22
|
-
# different suffix. Note that the URL doesn't have to really exist or be callable - the url_for system is just used to generate unique
|
23
|
-
# cache names that we can refer to when we need to expire the cache.
|
24
|
-
#
|
21
|
+
# That would result in a name such as "/topics/list/all_topics", avoiding conflicts with the action cache and with any fragments that use a
|
22
|
+
# different suffix. Note that the URL doesn't have to really exist or be callable - the url_for system is just used to generate unique
|
23
|
+
# cache names that we can refer to when we need to expire the cache.
|
24
|
+
#
|
25
25
|
# The expiration call for this example is:
|
26
|
-
#
|
26
|
+
#
|
27
27
|
# expire_fragment(:controller => "topics", :action => "list", :action_suffix => "all_topics")
|
28
28
|
module Fragments
|
29
|
-
# Given a key (as described in <tt>expire_fragment</tt>), returns a key suitable for use in reading,
|
29
|
+
# Given a key (as described in <tt>expire_fragment</tt>), returns a key suitable for use in reading,
|
30
30
|
# writing, or expiring a cached fragment. If the key is a hash, the generated key is the return
|
31
31
|
# value of url_for on that hash (without the protocol). All keys are prefixed with "views/" and uses
|
32
32
|
# ActiveSupport::Cache.expand_cache_key for the expansion.
|
@@ -50,7 +50,7 @@ module ActionController #:nodoc:
|
|
50
50
|
|
51
51
|
# Writes <tt>content</tt> to the location signified by <tt>key</tt> (see <tt>expire_fragment</tt> for acceptable formats)
|
52
52
|
def write_fragment(key, content, options = nil)
|
53
|
-
return unless cache_configured?
|
53
|
+
return content unless cache_configured?
|
54
54
|
|
55
55
|
key = fragment_cache_key(key)
|
56
56
|
|
@@ -83,15 +83,23 @@ module ActionController #:nodoc:
|
|
83
83
|
end
|
84
84
|
end
|
85
85
|
|
86
|
-
#
|
87
|
-
#
|
88
|
-
#
|
89
|
-
# *
|
90
|
-
#
|
91
|
-
#
|
92
|
-
#
|
93
|
-
#
|
94
|
-
# all
|
86
|
+
# Removes fragments from the cache.
|
87
|
+
#
|
88
|
+
# +key+ can take one of three forms:
|
89
|
+
# * String - This would normally take the form of a path, like
|
90
|
+
# <tt>"pages/45/notes"</tt>.
|
91
|
+
# * Hash - Treated as an implicit call to +url_for+, like
|
92
|
+
# <tt>{:controller => "pages", :action => "notes", :id => 45}</tt>
|
93
|
+
# * Regexp - Will remove any fragment that matches, so
|
94
|
+
# <tt>%r{pages/\d*/notes}</tt> might remove all notes. Make sure you
|
95
|
+
# don't use anchors in the regex (<tt>^</tt> or <tt>$</tt>) because
|
96
|
+
# the actual filename matched looks like
|
97
|
+
# <tt>./cache/filename/path.cache</tt>. Note: Regexp expiration is
|
98
|
+
# only supported on caches that can iterate over all keys (unlike
|
99
|
+
# memcached).
|
100
|
+
#
|
101
|
+
# +options+ is passed through to the cache store's <tt>delete</tt>
|
102
|
+
# method (or <tt>delete_matched</tt>, for Regexp keys.)
|
95
103
|
def expire_fragment(key, options = nil)
|
96
104
|
return unless cache_configured?
|
97
105
|
|
@@ -33,28 +33,26 @@ module ActionController #:nodoc:
|
|
33
33
|
#
|
34
34
|
# Additionally, you can expire caches using Sweepers that act on changes in the model to determine when a cache is supposed to be
|
35
35
|
# expired.
|
36
|
-
#
|
37
|
-
# == Setting the cache directory
|
38
|
-
#
|
39
|
-
# The cache directory should be the document root for the web server and is set using <tt>Base.page_cache_directory = "/document/root"</tt>.
|
40
|
-
# For Rails, this directory has already been set to Rails.public_path (which is usually set to <tt>RAILS_ROOT + "/public"</tt>). Changing
|
41
|
-
# this setting can be useful to avoid naming conflicts with files in <tt>public/</tt>, but doing so will likely require configuring your
|
42
|
-
# web server to look in the new location for cached files.
|
43
|
-
#
|
44
|
-
# == Setting the cache extension
|
45
|
-
#
|
46
|
-
# Most Rails requests do not have an extension, such as <tt>/weblog/new</tt>. In these cases, the page caching mechanism will add one in
|
47
|
-
# order to make it easy for the cached files to be picked up properly by the web server. By default, this cache extension is <tt>.html</tt>.
|
48
|
-
# If you want something else, like <tt>.php</tt> or <tt>.shtml</tt>, just set Base.page_cache_extension. In cases where a request already has an
|
49
|
-
# extension, such as <tt>.xml</tt> or <tt>.rss</tt>, page caching will not add an extension. This allows it to work well with RESTful apps.
|
50
36
|
module Pages
|
51
37
|
def self.included(base) #:nodoc:
|
52
38
|
base.extend(ClassMethods)
|
53
39
|
base.class_eval do
|
54
40
|
@@page_cache_directory = defined?(Rails.public_path) ? Rails.public_path : ""
|
41
|
+
##
|
42
|
+
# :singleton-method:
|
43
|
+
# The cache directory should be the document root for the web server and is set using <tt>Base.page_cache_directory = "/document/root"</tt>.
|
44
|
+
# For Rails, this directory has already been set to Rails.public_path (which is usually set to <tt>RAILS_ROOT + "/public"</tt>). Changing
|
45
|
+
# this setting can be useful to avoid naming conflicts with files in <tt>public/</tt>, but doing so will likely require configuring your
|
46
|
+
# web server to look in the new location for cached files.
|
55
47
|
cattr_accessor :page_cache_directory
|
56
48
|
|
57
49
|
@@page_cache_extension = '.html'
|
50
|
+
##
|
51
|
+
# :singleton-method:
|
52
|
+
# Most Rails requests do not have an extension, such as <tt>/weblog/new</tt>. In these cases, the page caching mechanism will add one in
|
53
|
+
# order to make it easy for the cached files to be picked up properly by the web server. By default, this cache extension is <tt>.html</tt>.
|
54
|
+
# If you want something else, like <tt>.php</tt> or <tt>.shtml</tt>, just set Base.page_cache_extension. In cases where a request already has an
|
55
|
+
# extension, such as <tt>.xml</tt> or <tt>.rss</tt>, page caching will not add an extension. This allows it to work well with RESTful apps.
|
58
56
|
cattr_accessor :page_cache_extension
|
59
57
|
end
|
60
58
|
end
|
@@ -147,7 +145,7 @@ module ActionController #:nodoc:
|
|
147
145
|
|
148
146
|
private
|
149
147
|
def caching_allowed
|
150
|
-
request.get? && response.
|
148
|
+
request.get? && response.status.to_i == 200
|
151
149
|
end
|
152
150
|
end
|
153
151
|
end
|
@@ -87,9 +87,9 @@ module ActionController #:nodoc:
|
|
87
87
|
__send__(action_callback_method_name) if respond_to?(action_callback_method_name, true)
|
88
88
|
end
|
89
89
|
|
90
|
-
def method_missing(method, *arguments)
|
90
|
+
def method_missing(method, *arguments, &block)
|
91
91
|
return if @controller.nil?
|
92
|
-
@controller.__send__(method, *arguments)
|
92
|
+
@controller.__send__(method, *arguments, &block)
|
93
93
|
end
|
94
94
|
end
|
95
95
|
end
|
@@ -1,185 +1,77 @@
|
|
1
1
|
require 'action_controller/cgi_ext'
|
2
|
-
require 'action_controller/session/cookie_store'
|
3
2
|
|
4
3
|
module ActionController #:nodoc:
|
5
|
-
class
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
# (default). Additionally, there is CGI::Session::DRbStore and CGI::Session::ActiveRecordStore. Read more about these in
|
11
|
-
# lib/action_controller/session.
|
12
|
-
# * <tt>:session_key</tt> - the parameter name used for the session id. Defaults to '_session_id'.
|
13
|
-
# * <tt>:session_id</tt> - the session id to use. If not provided, then it is retrieved from the +session_key+ cookie, or
|
14
|
-
# automatically generated for a new session.
|
15
|
-
# * <tt>:new_session</tt> - if true, force creation of a new session. If not set, a new session is only created if none currently
|
16
|
-
# exists. If false, a new session is never created, and if none currently exists and the +session_id+ option is not set,
|
17
|
-
# an ArgumentError is raised.
|
18
|
-
# * <tt>:session_expires</tt> - the time the current session expires, as a Time object. If not set, the session will continue
|
19
|
-
# indefinitely.
|
20
|
-
# * <tt>:session_domain</tt> - the hostname domain for which this session is valid. If not set, defaults to the hostname of the
|
21
|
-
# server.
|
22
|
-
# * <tt>:session_secure</tt> - if +true+, this session will only work over HTTPS.
|
23
|
-
# * <tt>:session_path</tt> - the path for which this session applies. Defaults to the directory of the CGI script.
|
24
|
-
# * <tt>:cookie_only</tt> - if +true+ (the default), session IDs will only be accepted from cookies and not from
|
25
|
-
# the query string or POST parameters. This protects against session fixation attacks.
|
26
|
-
def self.process_cgi(cgi = CGI.new, session_options = {})
|
27
|
-
new.process_cgi(cgi, session_options)
|
28
|
-
end
|
29
|
-
|
30
|
-
def process_cgi(cgi, session_options = {}) #:nodoc:
|
31
|
-
process(CgiRequest.new(cgi, session_options), CgiResponse.new(cgi)).out
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
class CgiRequest < AbstractRequest #:nodoc:
|
36
|
-
attr_accessor :cgi, :session_options
|
37
|
-
class SessionFixationAttempt < StandardError #:nodoc:
|
38
|
-
end
|
39
|
-
|
40
|
-
DEFAULT_SESSION_OPTIONS = {
|
41
|
-
:database_manager => CGI::Session::CookieStore, # store data in cookie
|
42
|
-
:prefix => "ruby_sess.", # prefix session file names
|
43
|
-
:session_path => "/", # available to all paths in app
|
44
|
-
:session_key => "_session_id",
|
45
|
-
:cookie_only => true,
|
46
|
-
:session_http_only=> true
|
47
|
-
}
|
48
|
-
|
49
|
-
def initialize(cgi, session_options = {})
|
50
|
-
@cgi = cgi
|
51
|
-
@session_options = session_options
|
52
|
-
@env = @cgi.__send__(:env_table)
|
53
|
-
super()
|
54
|
-
end
|
55
|
-
|
56
|
-
def query_string
|
57
|
-
qs = @cgi.query_string if @cgi.respond_to?(:query_string)
|
58
|
-
if !qs.blank?
|
59
|
-
qs
|
60
|
-
else
|
61
|
-
super
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
def body_stream #:nodoc:
|
66
|
-
@cgi.stdinput
|
67
|
-
end
|
68
|
-
|
69
|
-
def cookies
|
70
|
-
@cgi.cookies.freeze
|
71
|
-
end
|
72
|
-
|
73
|
-
def session
|
74
|
-
unless defined?(@session)
|
75
|
-
if @session_options == false
|
76
|
-
@session = Hash.new
|
77
|
-
else
|
78
|
-
stale_session_check! do
|
79
|
-
if cookie_only? && query_parameters[session_options_with_string_keys['session_key']]
|
80
|
-
raise SessionFixationAttempt
|
81
|
-
end
|
82
|
-
case value = session_options_with_string_keys['new_session']
|
83
|
-
when true
|
84
|
-
@session = new_session
|
85
|
-
when false
|
86
|
-
begin
|
87
|
-
@session = CGI::Session.new(@cgi, session_options_with_string_keys)
|
88
|
-
# CGI::Session raises ArgumentError if 'new_session' == false
|
89
|
-
# and no session cookie or query param is present.
|
90
|
-
rescue ArgumentError
|
91
|
-
@session = Hash.new
|
92
|
-
end
|
93
|
-
when nil
|
94
|
-
@session = CGI::Session.new(@cgi, session_options_with_string_keys)
|
95
|
-
else
|
96
|
-
raise ArgumentError, "Invalid new_session option: #{value}"
|
97
|
-
end
|
98
|
-
@session['__valid_session']
|
99
|
-
end
|
4
|
+
class CGIHandler
|
5
|
+
module ProperStream
|
6
|
+
def each
|
7
|
+
while line = gets
|
8
|
+
yield line
|
100
9
|
end
|
101
10
|
end
|
102
|
-
@session
|
103
|
-
end
|
104
11
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
end
|
109
|
-
|
110
|
-
def method_missing(method_id, *arguments)
|
111
|
-
@cgi.__send__(method_id, *arguments) rescue super
|
112
|
-
end
|
113
|
-
|
114
|
-
private
|
115
|
-
# Delete an old session if it exists then create a new one.
|
116
|
-
def new_session
|
117
|
-
if @session_options == false
|
118
|
-
Hash.new
|
12
|
+
def read(*args)
|
13
|
+
if args.empty?
|
14
|
+
super || ""
|
119
15
|
else
|
120
|
-
|
121
|
-
CGI::Session.new(@cgi, session_options_with_string_keys.merge("new_session" => true))
|
16
|
+
super
|
122
17
|
end
|
123
18
|
end
|
19
|
+
end
|
124
20
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
def stale_session_check!
|
130
|
-
yield
|
131
|
-
rescue ArgumentError => argument_error
|
132
|
-
if argument_error.message =~ %r{undefined class/module ([\w:]*\w)}
|
133
|
-
begin
|
134
|
-
# Note that the regexp does not allow $1 to end with a ':'
|
135
|
-
$1.constantize
|
136
|
-
rescue LoadError, NameError => const_error
|
137
|
-
raise ActionController::SessionRestoreError, <<-end_msg
|
138
|
-
Session contains objects whose class definition isn\'t available.
|
139
|
-
Remember to require the classes for all objects kept in the session.
|
140
|
-
(Original exception: #{const_error.message} [#{const_error.class}])
|
141
|
-
end_msg
|
142
|
-
end
|
21
|
+
def self.dispatch_cgi(app, cgi, out = $stdout)
|
22
|
+
env = cgi.__send__(:env_table)
|
23
|
+
env.delete "HTTP_CONTENT_LENGTH"
|
143
24
|
|
144
|
-
|
145
|
-
else
|
146
|
-
raise
|
147
|
-
end
|
148
|
-
end
|
25
|
+
cgi.stdinput.extend ProperStream
|
149
26
|
|
150
|
-
|
151
|
-
@session_options_with_string_keys ||= DEFAULT_SESSION_OPTIONS.merge(@session_options).stringify_keys
|
152
|
-
end
|
153
|
-
end
|
27
|
+
env["SCRIPT_NAME"] = "" if env["SCRIPT_NAME"] == "/"
|
154
28
|
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
29
|
+
env.update({
|
30
|
+
"rack.version" => [0,1],
|
31
|
+
"rack.input" => cgi.stdinput,
|
32
|
+
"rack.errors" => $stderr,
|
33
|
+
"rack.multithread" => false,
|
34
|
+
"rack.multiprocess" => true,
|
35
|
+
"rack.run_once" => false,
|
36
|
+
"rack.url_scheme" => ["yes", "on", "1"].include?(env["HTTPS"]) ? "https" : "http"
|
37
|
+
})
|
160
38
|
|
161
|
-
|
162
|
-
|
163
|
-
|
39
|
+
env["QUERY_STRING"] ||= ""
|
40
|
+
env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"]
|
41
|
+
env["REQUEST_PATH"] ||= "/"
|
42
|
+
env.delete "PATH_INFO" if env["PATH_INFO"] == ""
|
164
43
|
|
44
|
+
status, headers, body = app.call(env)
|
165
45
|
begin
|
166
|
-
|
46
|
+
out.binmode if out.respond_to?(:binmode)
|
47
|
+
out.sync = false if out.respond_to?(:sync=)
|
167
48
|
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
# #syswrite.
|
173
|
-
output.flush if output.respond_to?(:flush)
|
174
|
-
@body.call(self, output)
|
175
|
-
else
|
176
|
-
output.write(@body)
|
49
|
+
headers['Status'] = status.to_s
|
50
|
+
|
51
|
+
if headers.include?('Set-Cookie')
|
52
|
+
headers['cookie'] = headers.delete('Set-Cookie').split("\n")
|
177
53
|
end
|
178
54
|
|
179
|
-
|
180
|
-
|
181
|
-
|
55
|
+
out.write(cgi.header(headers))
|
56
|
+
|
57
|
+
body.each { |part|
|
58
|
+
out.write part
|
59
|
+
out.flush if out.respond_to?(:flush)
|
60
|
+
}
|
61
|
+
ensure
|
62
|
+
body.close if body.respond_to?(:close)
|
182
63
|
end
|
183
64
|
end
|
184
65
|
end
|
66
|
+
|
67
|
+
class CgiRequest #:nodoc:
|
68
|
+
DEFAULT_SESSION_OPTIONS = {
|
69
|
+
:database_manager => nil,
|
70
|
+
:prefix => "ruby_sess.",
|
71
|
+
:session_path => "/",
|
72
|
+
:session_key => "_session_id",
|
73
|
+
:cookie_only => true,
|
74
|
+
:session_http_only => true
|
75
|
+
}
|
76
|
+
end
|
185
77
|
end
|