actionpack 3.2.22.5 → 5.2.4
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.
- checksums.yaml +5 -5
- data/CHANGELOG.md +279 -603
- data/MIT-LICENSE +1 -1
- data/README.rdoc +13 -297
- data/lib/abstract_controller/asset_paths.rb +4 -2
- data/lib/abstract_controller/base.rb +82 -52
- data/lib/abstract_controller/caching/fragments.rb +166 -0
- data/lib/abstract_controller/caching.rb +66 -0
- data/lib/abstract_controller/callbacks.rb +117 -103
- data/lib/abstract_controller/collector.rb +18 -7
- data/lib/abstract_controller/error.rb +6 -0
- data/lib/abstract_controller/helpers.rb +65 -38
- data/lib/abstract_controller/logger.rb +3 -2
- data/lib/abstract_controller/railties/routes_helpers.rb +5 -3
- data/lib/abstract_controller/rendering.rb +77 -129
- data/lib/abstract_controller/translation.rb +21 -3
- data/lib/abstract_controller/url_for.rb +9 -7
- data/lib/abstract_controller.rb +12 -13
- data/lib/action_controller/api/api_rendering.rb +16 -0
- data/lib/action_controller/api.rb +149 -0
- data/lib/action_controller/base.rb +81 -40
- data/lib/action_controller/caching.rb +22 -62
- data/lib/action_controller/form_builder.rb +50 -0
- data/lib/action_controller/log_subscriber.rb +30 -18
- data/lib/action_controller/metal/basic_implicit_render.rb +13 -0
- data/lib/action_controller/metal/conditional_get.rb +190 -47
- data/lib/action_controller/metal/content_security_policy.rb +52 -0
- data/lib/action_controller/metal/cookies.rb +3 -3
- data/lib/action_controller/metal/data_streaming.rb +40 -65
- data/lib/action_controller/metal/etag_with_flash.rb +18 -0
- data/lib/action_controller/metal/etag_with_template_digest.rb +57 -0
- data/lib/action_controller/metal/exceptions.rb +19 -12
- data/lib/action_controller/metal/flash.rb +42 -9
- data/lib/action_controller/metal/force_ssl.rb +79 -19
- data/lib/action_controller/metal/head.rb +35 -10
- data/lib/action_controller/metal/helpers.rb +31 -21
- data/lib/action_controller/metal/http_authentication.rb +182 -134
- data/lib/action_controller/metal/implicit_render.rb +62 -8
- data/lib/action_controller/metal/instrumentation.rb +28 -26
- data/lib/action_controller/metal/live.rb +312 -0
- data/lib/action_controller/metal/mime_responds.rb +159 -163
- data/lib/action_controller/metal/parameter_encoding.rb +51 -0
- data/lib/action_controller/metal/params_wrapper.rb +146 -93
- data/lib/action_controller/metal/redirecting.rb +80 -56
- data/lib/action_controller/metal/renderers.rb +119 -47
- data/lib/action_controller/metal/rendering.rb +89 -32
- data/lib/action_controller/metal/request_forgery_protection.rb +373 -41
- data/lib/action_controller/metal/rescue.rb +9 -16
- data/lib/action_controller/metal/streaming.rb +39 -45
- data/lib/action_controller/metal/strong_parameters.rb +1086 -0
- data/lib/action_controller/metal/testing.rb +8 -29
- data/lib/action_controller/metal/url_for.rb +43 -32
- data/lib/action_controller/metal.rb +112 -106
- data/lib/action_controller/railtie.rb +56 -18
- data/lib/action_controller/railties/helpers.rb +24 -0
- data/lib/action_controller/renderer.rb +117 -0
- data/lib/action_controller/template_assertions.rb +11 -0
- data/lib/action_controller/test_case.rb +402 -347
- data/lib/action_controller.rb +31 -30
- data/lib/action_dispatch/http/cache.rb +133 -34
- data/lib/action_dispatch/http/content_security_policy.rb +272 -0
- data/lib/action_dispatch/http/filter_parameters.rb +40 -24
- data/lib/action_dispatch/http/filter_redirect.rb +37 -0
- data/lib/action_dispatch/http/headers.rb +117 -16
- data/lib/action_dispatch/http/mime_negotiation.rb +98 -33
- data/lib/action_dispatch/http/mime_type.rb +198 -146
- data/lib/action_dispatch/http/mime_types.rb +22 -7
- data/lib/action_dispatch/http/parameter_filter.rb +61 -49
- data/lib/action_dispatch/http/parameters.rb +94 -51
- data/lib/action_dispatch/http/rack_cache.rb +4 -3
- data/lib/action_dispatch/http/request.rb +262 -117
- data/lib/action_dispatch/http/response.rb +400 -86
- data/lib/action_dispatch/http/upload.rb +66 -29
- data/lib/action_dispatch/http/url.rb +232 -60
- data/lib/action_dispatch/journey/formatter.rb +189 -0
- data/lib/action_dispatch/journey/gtg/builder.rb +164 -0
- data/lib/action_dispatch/journey/gtg/simulator.rb +41 -0
- data/lib/action_dispatch/journey/gtg/transition_table.rb +158 -0
- data/lib/action_dispatch/journey/nfa/builder.rb +78 -0
- data/lib/action_dispatch/journey/nfa/dot.rb +36 -0
- data/lib/action_dispatch/journey/nfa/simulator.rb +49 -0
- data/lib/action_dispatch/journey/nfa/transition_table.rb +120 -0
- data/lib/action_dispatch/journey/nodes/node.rb +140 -0
- data/lib/action_dispatch/journey/parser.rb +199 -0
- data/lib/action_dispatch/journey/parser.y +50 -0
- data/lib/action_dispatch/journey/parser_extras.rb +31 -0
- data/lib/action_dispatch/journey/path/pattern.rb +199 -0
- data/lib/action_dispatch/journey/route.rb +203 -0
- data/lib/action_dispatch/journey/router/utils.rb +102 -0
- data/lib/action_dispatch/journey/router.rb +156 -0
- data/lib/action_dispatch/journey/routes.rb +82 -0
- data/lib/action_dispatch/journey/scanner.rb +64 -0
- data/lib/action_dispatch/journey/visitors.rb +268 -0
- data/lib/action_dispatch/journey/visualizer/fsm.css +30 -0
- data/lib/action_dispatch/journey/visualizer/fsm.js +134 -0
- data/lib/action_dispatch/journey/visualizer/index.html.erb +52 -0
- data/lib/action_dispatch/journey.rb +7 -0
- data/lib/action_dispatch/middleware/callbacks.rb +17 -13
- data/lib/action_dispatch/middleware/cookies.rb +494 -162
- data/lib/action_dispatch/middleware/debug_exceptions.rb +176 -53
- data/lib/action_dispatch/middleware/debug_locks.rb +124 -0
- data/lib/action_dispatch/middleware/exception_wrapper.rb +103 -38
- data/lib/action_dispatch/middleware/executor.rb +21 -0
- data/lib/action_dispatch/middleware/flash.rb +128 -91
- data/lib/action_dispatch/middleware/public_exceptions.rb +43 -16
- data/lib/action_dispatch/middleware/reloader.rb +6 -83
- data/lib/action_dispatch/middleware/remote_ip.rb +151 -49
- data/lib/action_dispatch/middleware/request_id.rb +19 -15
- data/lib/action_dispatch/middleware/session/abstract_store.rb +38 -34
- data/lib/action_dispatch/middleware/session/cache_store.rb +14 -9
- data/lib/action_dispatch/middleware/session/cookie_store.rb +94 -44
- data/lib/action_dispatch/middleware/session/mem_cache_store.rb +15 -4
- data/lib/action_dispatch/middleware/show_exceptions.rb +36 -61
- data/lib/action_dispatch/middleware/ssl.rb +150 -0
- data/lib/action_dispatch/middleware/stack.rb +33 -41
- data/lib/action_dispatch/middleware/static.rb +92 -48
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +22 -0
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb +23 -0
- data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +27 -0
- data/lib/action_dispatch/middleware/templates/rescues/_source.text.erb +8 -0
- data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +52 -0
- data/lib/action_dispatch/middleware/templates/rescues/_trace.text.erb +9 -0
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +16 -0
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +9 -0
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +21 -0
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +13 -0
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +134 -5
- data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +11 -0
- data/lib/action_dispatch/middleware/templates/rescues/missing_template.text.erb +3 -0
- data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +32 -0
- data/lib/action_dispatch/middleware/templates/rescues/routing_error.text.erb +11 -0
- data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +20 -0
- data/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb +7 -0
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +6 -0
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.text.erb +3 -0
- data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +16 -0
- data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +200 -0
- data/lib/action_dispatch/railtie.rb +29 -8
- data/lib/action_dispatch/request/session.rb +234 -0
- data/lib/action_dispatch/request/utils.rb +78 -0
- data/lib/action_dispatch/routing/endpoint.rb +17 -0
- data/lib/action_dispatch/routing/inspector.rb +225 -0
- data/lib/action_dispatch/routing/mapper.rb +1329 -582
- data/lib/action_dispatch/routing/polymorphic_routes.rb +237 -94
- data/lib/action_dispatch/routing/redirection.rb +120 -50
- data/lib/action_dispatch/routing/route_set.rb +545 -322
- data/lib/action_dispatch/routing/routes_proxy.rb +37 -7
- data/lib/action_dispatch/routing/url_for.rb +103 -34
- data/lib/action_dispatch/routing.rb +66 -99
- data/lib/action_dispatch/system_test_case.rb +147 -0
- data/lib/action_dispatch/system_testing/browser.rb +49 -0
- data/lib/action_dispatch/system_testing/driver.rb +59 -0
- data/lib/action_dispatch/system_testing/server.rb +31 -0
- data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +96 -0
- data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +31 -0
- data/lib/action_dispatch/system_testing/test_helpers/undef_methods.rb +26 -0
- data/lib/action_dispatch/testing/assertion_response.rb +47 -0
- data/lib/action_dispatch/testing/assertions/response.rb +53 -42
- data/lib/action_dispatch/testing/assertions/routing.rb +79 -74
- data/lib/action_dispatch/testing/assertions.rb +15 -9
- data/lib/action_dispatch/testing/integration.rb +361 -207
- data/lib/action_dispatch/testing/request_encoder.rb +55 -0
- data/lib/action_dispatch/testing/test_process.rb +28 -19
- data/lib/action_dispatch/testing/test_request.rb +30 -33
- data/lib/action_dispatch/testing/test_response.rb +35 -11
- data/lib/action_dispatch.rb +42 -32
- data/lib/action_pack/gem_version.rb +17 -0
- data/lib/action_pack/version.rb +7 -7
- data/lib/action_pack.rb +4 -2
- metadata +116 -175
- data/lib/abstract_controller/layouts.rb +0 -423
- data/lib/abstract_controller/view_paths.rb +0 -96
- data/lib/action_controller/caching/actions.rb +0 -185
- data/lib/action_controller/caching/fragments.rb +0 -127
- data/lib/action_controller/caching/pages.rb +0 -187
- data/lib/action_controller/caching/sweeping.rb +0 -97
- data/lib/action_controller/deprecated/integration_test.rb +0 -2
- data/lib/action_controller/deprecated/performance_test.rb +0 -1
- data/lib/action_controller/deprecated.rb +0 -3
- data/lib/action_controller/metal/compatibility.rb +0 -65
- data/lib/action_controller/metal/hide_actions.rb +0 -41
- data/lib/action_controller/metal/rack_delegation.rb +0 -26
- data/lib/action_controller/metal/responder.rb +0 -286
- data/lib/action_controller/metal/session_management.rb +0 -14
- data/lib/action_controller/middleware.rb +0 -39
- data/lib/action_controller/railties/paths.rb +0 -25
- data/lib/action_controller/record_identifier.rb +0 -85
- data/lib/action_controller/vendor/html-scanner/html/document.rb +0 -68
- data/lib/action_controller/vendor/html-scanner/html/node.rb +0 -532
- data/lib/action_controller/vendor/html-scanner/html/sanitizer.rb +0 -177
- data/lib/action_controller/vendor/html-scanner/html/selector.rb +0 -830
- data/lib/action_controller/vendor/html-scanner/html/tokenizer.rb +0 -107
- data/lib/action_controller/vendor/html-scanner/html/version.rb +0 -11
- data/lib/action_controller/vendor/html-scanner.rb +0 -20
- data/lib/action_dispatch/middleware/best_standards_support.rb +0 -30
- data/lib/action_dispatch/middleware/body_proxy.rb +0 -30
- data/lib/action_dispatch/middleware/head.rb +0 -18
- data/lib/action_dispatch/middleware/params_parser.rb +0 -75
- data/lib/action_dispatch/middleware/rescue.rb +0 -26
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb +0 -31
- data/lib/action_dispatch/middleware/templates/rescues/_trace.erb +0 -26
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb +0 -10
- data/lib/action_dispatch/middleware/templates/rescues/missing_template.erb +0 -2
- data/lib/action_dispatch/middleware/templates/rescues/routing_error.erb +0 -15
- data/lib/action_dispatch/middleware/templates/rescues/template_error.erb +0 -17
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.erb +0 -2
- data/lib/action_dispatch/testing/assertions/dom.rb +0 -37
- data/lib/action_dispatch/testing/assertions/selector.rb +0 -435
- data/lib/action_dispatch/testing/assertions/tag.rb +0 -138
- data/lib/action_dispatch/testing/performance_test.rb +0 -10
- data/lib/action_view/asset_paths.rb +0 -142
- data/lib/action_view/base.rb +0 -220
- data/lib/action_view/buffers.rb +0 -43
- data/lib/action_view/context.rb +0 -36
- data/lib/action_view/flows.rb +0 -79
- data/lib/action_view/helpers/active_model_helper.rb +0 -50
- data/lib/action_view/helpers/asset_paths.rb +0 -7
- data/lib/action_view/helpers/asset_tag_helper.rb +0 -457
- data/lib/action_view/helpers/asset_tag_helpers/asset_include_tag.rb +0 -146
- data/lib/action_view/helpers/asset_tag_helpers/asset_paths.rb +0 -93
- data/lib/action_view/helpers/asset_tag_helpers/javascript_tag_helpers.rb +0 -193
- data/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb +0 -148
- data/lib/action_view/helpers/atom_feed_helper.rb +0 -200
- data/lib/action_view/helpers/cache_helper.rb +0 -64
- data/lib/action_view/helpers/capture_helper.rb +0 -203
- data/lib/action_view/helpers/controller_helper.rb +0 -25
- data/lib/action_view/helpers/csrf_helper.rb +0 -32
- data/lib/action_view/helpers/date_helper.rb +0 -1062
- data/lib/action_view/helpers/debug_helper.rb +0 -40
- data/lib/action_view/helpers/form_helper.rb +0 -1486
- data/lib/action_view/helpers/form_options_helper.rb +0 -658
- data/lib/action_view/helpers/form_tag_helper.rb +0 -685
- data/lib/action_view/helpers/javascript_helper.rb +0 -110
- data/lib/action_view/helpers/number_helper.rb +0 -622
- data/lib/action_view/helpers/output_safety_helper.rb +0 -38
- data/lib/action_view/helpers/record_tag_helper.rb +0 -111
- data/lib/action_view/helpers/rendering_helper.rb +0 -92
- data/lib/action_view/helpers/sanitize_helper.rb +0 -259
- data/lib/action_view/helpers/tag_helper.rb +0 -167
- data/lib/action_view/helpers/text_helper.rb +0 -426
- data/lib/action_view/helpers/translation_helper.rb +0 -91
- data/lib/action_view/helpers/url_helper.rb +0 -693
- data/lib/action_view/helpers.rb +0 -60
- data/lib/action_view/locale/en.yml +0 -160
- data/lib/action_view/log_subscriber.rb +0 -28
- data/lib/action_view/lookup_context.rb +0 -258
- data/lib/action_view/path_set.rb +0 -101
- data/lib/action_view/railtie.rb +0 -55
- data/lib/action_view/renderer/abstract_renderer.rb +0 -41
- data/lib/action_view/renderer/partial_renderer.rb +0 -415
- data/lib/action_view/renderer/renderer.rb +0 -61
- data/lib/action_view/renderer/streaming_template_renderer.rb +0 -106
- data/lib/action_view/renderer/template_renderer.rb +0 -95
- data/lib/action_view/template/error.rb +0 -128
- data/lib/action_view/template/handlers/builder.rb +0 -26
- data/lib/action_view/template/handlers/erb.rb +0 -125
- data/lib/action_view/template/handlers.rb +0 -50
- data/lib/action_view/template/resolver.rb +0 -298
- data/lib/action_view/template/text.rb +0 -30
- data/lib/action_view/template.rb +0 -337
- data/lib/action_view/test_case.rb +0 -246
- data/lib/action_view/testing/resolvers.rb +0 -49
- data/lib/action_view.rb +0 -84
- data/lib/sprockets/assets.rake +0 -99
- data/lib/sprockets/bootstrap.rb +0 -37
- data/lib/sprockets/compressors.rb +0 -83
- data/lib/sprockets/helpers/isolated_helper.rb +0 -13
- data/lib/sprockets/helpers/rails_helper.rb +0 -182
- data/lib/sprockets/helpers.rb +0 -6
- data/lib/sprockets/railtie.rb +0 -62
- data/lib/sprockets/static_compiler.rb +0 -56
@@ -1,14 +1,25 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "action_dispatch/middleware/session/abstract_store"
|
4
|
+
begin
|
5
|
+
require "rack/session/dalli"
|
6
|
+
rescue LoadError => e
|
7
|
+
$stderr.puts "You don't have dalli installed in your application. Please add it to your Gemfile and run bundle install"
|
8
|
+
raise e
|
9
|
+
end
|
3
10
|
|
4
11
|
module ActionDispatch
|
5
12
|
module Session
|
6
|
-
|
13
|
+
# A session store that uses MemCache to implement storage.
|
14
|
+
#
|
15
|
+
# ==== Options
|
16
|
+
# * <tt>expire_after</tt> - The length of time a session will be stored before automatically expiring.
|
17
|
+
class MemCacheStore < Rack::Session::Dalli
|
7
18
|
include Compatibility
|
8
19
|
include StaleSessionCheck
|
20
|
+
include SessionObject
|
9
21
|
|
10
22
|
def initialize(app, options = {})
|
11
|
-
require 'memcache'
|
12
23
|
options[:expire_after] ||= options[:expires]
|
13
24
|
super
|
14
25
|
end
|
@@ -1,87 +1,62 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "action_dispatch/http/request"
|
4
|
+
require "action_dispatch/middleware/exception_wrapper"
|
4
5
|
|
5
6
|
module ActionDispatch
|
6
7
|
# This middleware rescues any exception returned by the application
|
7
8
|
# and calls an exceptions app that will wrap it in a format for the end user.
|
8
9
|
#
|
9
10
|
# The exceptions app should be passed as parameter on initialization
|
10
|
-
# of ShowExceptions.
|
11
|
+
# of ShowExceptions. Every time there is an exception, ShowExceptions will
|
11
12
|
# store the exception in env["action_dispatch.exception"], rewrite the
|
12
|
-
# PATH_INFO to the exception status code and call the
|
13
|
-
#
|
13
|
+
# PATH_INFO to the exception status code and call the Rack app.
|
14
|
+
#
|
14
15
|
# If the application returns a "X-Cascade" pass response, this middleware
|
15
16
|
# will send an empty response as result with the correct status code.
|
16
17
|
# If any exception happens inside the exceptions app, this middleware
|
17
18
|
# catches the exceptions and returns a FAILSAFE_RESPONSE.
|
18
19
|
class ShowExceptions
|
19
|
-
FAILSAFE_RESPONSE = [500, {
|
20
|
-
["
|
21
|
-
"If you are the administrator of this website, then please read this web "
|
22
|
-
"application's log file and/or the web server's log file to find out what "
|
23
|
-
"went wrong
|
24
|
-
|
25
|
-
class << self
|
26
|
-
def rescue_responses
|
27
|
-
ActiveSupport::Deprecation.warn "ActionDispatch::ShowExceptions.rescue_responses is deprecated. " \
|
28
|
-
"Please configure your exceptions using a railtie or in your application config instead."
|
29
|
-
ExceptionWrapper.rescue_responses
|
30
|
-
end
|
31
|
-
|
32
|
-
def rescue_templates
|
33
|
-
ActiveSupport::Deprecation.warn "ActionDispatch::ShowExceptions.rescue_templates is deprecated. " \
|
34
|
-
"Please configure your exceptions using a railtie or in your application config instead."
|
35
|
-
ExceptionWrapper.rescue_templates
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
def initialize(app, exceptions_app = nil)
|
40
|
-
if [true, false].include?(exceptions_app)
|
41
|
-
ActiveSupport::Deprecation.warn "Passing consider_all_requests_local option to ActionDispatch::ShowExceptions middleware no longer works"
|
42
|
-
exceptions_app = nil
|
43
|
-
end
|
44
|
-
|
45
|
-
if exceptions_app.nil?
|
46
|
-
raise ArgumentError, "You need to pass an exceptions_app when initializing ActionDispatch::ShowExceptions. " \
|
47
|
-
"In case you want to render pages from a public path, you can use ActionDispatch::PublicExceptions.new('path/to/public')"
|
48
|
-
end
|
20
|
+
FAILSAFE_RESPONSE = [500, { "Content-Type" => "text/plain" },
|
21
|
+
["500 Internal Server Error\n" \
|
22
|
+
"If you are the administrator of this website, then please read this web " \
|
23
|
+
"application's log file and/or the web server's log file to find out what " \
|
24
|
+
"went wrong."]]
|
49
25
|
|
26
|
+
def initialize(app, exceptions_app)
|
50
27
|
@app = app
|
51
28
|
@exceptions_app = exceptions_app
|
52
29
|
end
|
53
30
|
|
54
31
|
def call(env)
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
32
|
+
request = ActionDispatch::Request.new env
|
33
|
+
@app.call(env)
|
34
|
+
rescue Exception => exception
|
35
|
+
if request.show_exceptions?
|
36
|
+
render_exception(request, exception)
|
37
|
+
else
|
38
|
+
raise exception
|
59
39
|
end
|
60
|
-
|
61
|
-
response || render_exception(env, exception)
|
62
40
|
end
|
63
41
|
|
64
42
|
private
|
65
43
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
$stderr.puts "Error during failsafe response: #{failsafe_error}\n #{failsafe_error.backtrace * "\n "}"
|
80
|
-
FAILSAFE_RESPONSE
|
81
|
-
end
|
44
|
+
def render_exception(request, exception)
|
45
|
+
backtrace_cleaner = request.get_header "action_dispatch.backtrace_cleaner"
|
46
|
+
wrapper = ExceptionWrapper.new(backtrace_cleaner, exception)
|
47
|
+
status = wrapper.status_code
|
48
|
+
request.set_header "action_dispatch.exception", wrapper.exception
|
49
|
+
request.set_header "action_dispatch.original_path", request.path_info
|
50
|
+
request.path_info = "/#{status}"
|
51
|
+
response = @exceptions_app.call(request.env)
|
52
|
+
response[1]["X-Cascade"] == "pass" ? pass_response(status) : response
|
53
|
+
rescue Exception => failsafe_error
|
54
|
+
$stderr.puts "Error during failsafe response: #{failsafe_error}\n #{failsafe_error.backtrace * "\n "}"
|
55
|
+
FAILSAFE_RESPONSE
|
56
|
+
end
|
82
57
|
|
83
|
-
|
84
|
-
|
85
|
-
|
58
|
+
def pass_response(status)
|
59
|
+
[status, { "Content-Type" => "text/html; charset=#{Response.default_charset}", "Content-Length" => "0" }, []]
|
60
|
+
end
|
86
61
|
end
|
87
62
|
end
|
@@ -0,0 +1,150 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActionDispatch
|
4
|
+
# This middleware is added to the stack when <tt>config.force_ssl = true</tt>, and is passed
|
5
|
+
# the options set in +config.ssl_options+. It does three jobs to enforce secure HTTP
|
6
|
+
# requests:
|
7
|
+
#
|
8
|
+
# 1. <b>TLS redirect</b>: Permanently redirects +http://+ requests to +https://+
|
9
|
+
# with the same URL host, path, etc. Enabled by default. Set +config.ssl_options+
|
10
|
+
# to modify the destination URL
|
11
|
+
# (e.g. <tt>redirect: { host: "secure.widgets.com", port: 8080 }</tt>), or set
|
12
|
+
# <tt>redirect: false</tt> to disable this feature.
|
13
|
+
#
|
14
|
+
# Requests can opt-out of redirection with +exclude+:
|
15
|
+
#
|
16
|
+
# config.ssl_options = { redirect: { exclude: -> request { request.path =~ /healthcheck/ } } }
|
17
|
+
#
|
18
|
+
# Cookies will not be flagged as secure for excluded requests.
|
19
|
+
#
|
20
|
+
# 2. <b>Secure cookies</b>: Sets the +secure+ flag on cookies to tell browsers they
|
21
|
+
# must not be sent along with +http://+ requests. Enabled by default. Set
|
22
|
+
# +config.ssl_options+ with <tt>secure_cookies: false</tt> to disable this feature.
|
23
|
+
#
|
24
|
+
# 3. <b>HTTP Strict Transport Security (HSTS)</b>: Tells the browser to remember
|
25
|
+
# this site as TLS-only and automatically redirect non-TLS requests.
|
26
|
+
# Enabled by default. Configure +config.ssl_options+ with <tt>hsts: false</tt> to disable.
|
27
|
+
#
|
28
|
+
# Set +config.ssl_options+ with <tt>hsts: { ... }</tt> to configure HSTS:
|
29
|
+
#
|
30
|
+
# * +expires+: How long, in seconds, these settings will stick. The minimum
|
31
|
+
# required to qualify for browser preload lists is 1 year. Defaults to
|
32
|
+
# 1 year (recommended).
|
33
|
+
#
|
34
|
+
# * +subdomains+: Set to +true+ to tell the browser to apply these settings
|
35
|
+
# to all subdomains. This protects your cookies from interception by a
|
36
|
+
# vulnerable site on a subdomain. Defaults to +true+.
|
37
|
+
#
|
38
|
+
# * +preload+: Advertise that this site may be included in browsers'
|
39
|
+
# preloaded HSTS lists. HSTS protects your site on every visit <i>except the
|
40
|
+
# first visit</i> since it hasn't seen your HSTS header yet. To close this
|
41
|
+
# gap, browser vendors include a baked-in list of HSTS-enabled sites.
|
42
|
+
# Go to https://hstspreload.org to submit your site for inclusion.
|
43
|
+
# Defaults to +false+.
|
44
|
+
#
|
45
|
+
# To turn off HSTS, omitting the header is not enough. Browsers will remember the
|
46
|
+
# original HSTS directive until it expires. Instead, use the header to tell browsers to
|
47
|
+
# expire HSTS immediately. Setting <tt>hsts: false</tt> is a shortcut for
|
48
|
+
# <tt>hsts: { expires: 0 }</tt>.
|
49
|
+
class SSL
|
50
|
+
# :stopdoc:
|
51
|
+
|
52
|
+
# Default to 1 year, the minimum for browser preload lists.
|
53
|
+
HSTS_EXPIRES_IN = 31536000
|
54
|
+
|
55
|
+
def self.default_hsts_options
|
56
|
+
{ expires: HSTS_EXPIRES_IN, subdomains: true, preload: false }
|
57
|
+
end
|
58
|
+
|
59
|
+
def initialize(app, redirect: {}, hsts: {}, secure_cookies: true)
|
60
|
+
@app = app
|
61
|
+
|
62
|
+
@redirect = redirect
|
63
|
+
|
64
|
+
@exclude = @redirect && @redirect[:exclude] || proc { !@redirect }
|
65
|
+
@secure_cookies = secure_cookies
|
66
|
+
|
67
|
+
@hsts_header = build_hsts_header(normalize_hsts_options(hsts))
|
68
|
+
end
|
69
|
+
|
70
|
+
def call(env)
|
71
|
+
request = Request.new env
|
72
|
+
|
73
|
+
if request.ssl?
|
74
|
+
@app.call(env).tap do |status, headers, body|
|
75
|
+
set_hsts_header! headers
|
76
|
+
flag_cookies_as_secure! headers if @secure_cookies && !@exclude.call(request)
|
77
|
+
end
|
78
|
+
else
|
79
|
+
return redirect_to_https request unless @exclude.call(request)
|
80
|
+
@app.call(env)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
def set_hsts_header!(headers)
|
86
|
+
headers["Strict-Transport-Security".freeze] ||= @hsts_header
|
87
|
+
end
|
88
|
+
|
89
|
+
def normalize_hsts_options(options)
|
90
|
+
case options
|
91
|
+
# Explicitly disabling HSTS clears the existing setting from browsers
|
92
|
+
# by setting expiry to 0.
|
93
|
+
when false
|
94
|
+
self.class.default_hsts_options.merge(expires: 0)
|
95
|
+
# Default to enabled, with default options.
|
96
|
+
when nil, true
|
97
|
+
self.class.default_hsts_options
|
98
|
+
else
|
99
|
+
self.class.default_hsts_options.merge(options)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
# https://tools.ietf.org/html/rfc6797#section-6.1
|
104
|
+
def build_hsts_header(hsts)
|
105
|
+
value = "max-age=#{hsts[:expires].to_i}".dup
|
106
|
+
value << "; includeSubDomains" if hsts[:subdomains]
|
107
|
+
value << "; preload" if hsts[:preload]
|
108
|
+
value
|
109
|
+
end
|
110
|
+
|
111
|
+
def flag_cookies_as_secure!(headers)
|
112
|
+
if cookies = headers["Set-Cookie".freeze]
|
113
|
+
cookies = cookies.split("\n".freeze)
|
114
|
+
|
115
|
+
headers["Set-Cookie".freeze] = cookies.map { |cookie|
|
116
|
+
if cookie !~ /;\s*secure\s*(;|$)/i
|
117
|
+
"#{cookie}; secure"
|
118
|
+
else
|
119
|
+
cookie
|
120
|
+
end
|
121
|
+
}.join("\n".freeze)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def redirect_to_https(request)
|
126
|
+
[ @redirect.fetch(:status, redirection_status(request)),
|
127
|
+
{ "Content-Type" => "text/html",
|
128
|
+
"Location" => https_location_for(request) },
|
129
|
+
@redirect.fetch(:body, []) ]
|
130
|
+
end
|
131
|
+
|
132
|
+
def redirection_status(request)
|
133
|
+
if request.get? || request.head?
|
134
|
+
301 # Issue a permanent redirect via a GET request.
|
135
|
+
else
|
136
|
+
307 # Issue a fresh request redirect to preserve the HTTP method.
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def https_location_for(request)
|
141
|
+
host = @redirect[:host] || request.host
|
142
|
+
port = @redirect[:port] || request.port
|
143
|
+
|
144
|
+
location = "https://#{host}".dup
|
145
|
+
location << ":#{port}" if port != 80 && port != 443
|
146
|
+
location << request.fullpath
|
147
|
+
location
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
@@ -1,28 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "active_support/inflector/methods"
|
2
4
|
require "active_support/dependencies"
|
3
5
|
|
4
6
|
module ActionDispatch
|
5
7
|
class MiddlewareStack
|
6
8
|
class Middleware
|
7
|
-
attr_reader :args, :block, :
|
8
|
-
|
9
|
-
def initialize(klass_or_name, *args, &block)
|
10
|
-
@klass = nil
|
11
|
-
|
12
|
-
if klass_or_name.respond_to?(:name)
|
13
|
-
@klass = klass_or_name
|
14
|
-
@name = @klass.name
|
15
|
-
else
|
16
|
-
@name = klass_or_name.to_s
|
17
|
-
end
|
9
|
+
attr_reader :args, :block, :klass
|
18
10
|
|
19
|
-
|
20
|
-
@
|
11
|
+
def initialize(klass, args, block)
|
12
|
+
@klass = klass
|
13
|
+
@args = args
|
14
|
+
@block = block
|
21
15
|
end
|
22
16
|
|
23
|
-
def klass
|
24
|
-
@klass || classcache[@name]
|
25
|
-
end
|
17
|
+
def name; klass.name; end
|
26
18
|
|
27
19
|
def ==(middleware)
|
28
20
|
case middleware
|
@@ -30,24 +22,20 @@ module ActionDispatch
|
|
30
22
|
klass == middleware.klass
|
31
23
|
when Class
|
32
24
|
klass == middleware
|
33
|
-
else
|
34
|
-
normalize(@name) == normalize(middleware)
|
35
25
|
end
|
36
26
|
end
|
37
27
|
|
38
28
|
def inspect
|
39
|
-
klass.
|
29
|
+
if klass.is_a?(Class)
|
30
|
+
klass.to_s
|
31
|
+
else
|
32
|
+
klass.class.to_s
|
33
|
+
end
|
40
34
|
end
|
41
35
|
|
42
36
|
def build(app)
|
43
37
|
klass.new(app, *args, &block)
|
44
38
|
end
|
45
|
-
|
46
|
-
private
|
47
|
-
|
48
|
-
def normalize(object)
|
49
|
-
object.to_s.strip.sub(/^::/, '')
|
50
|
-
end
|
51
39
|
end
|
52
40
|
|
53
41
|
include Enumerable
|
@@ -75,14 +63,17 @@ module ActionDispatch
|
|
75
63
|
middlewares[i]
|
76
64
|
end
|
77
65
|
|
66
|
+
def unshift(klass, *args, &block)
|
67
|
+
middlewares.unshift(build_middleware(klass, args, block))
|
68
|
+
end
|
69
|
+
|
78
70
|
def initialize_copy(other)
|
79
71
|
self.middlewares = other.middlewares.dup
|
80
72
|
end
|
81
73
|
|
82
|
-
def insert(index, *args, &block)
|
74
|
+
def insert(index, klass, *args, &block)
|
83
75
|
index = assert_index(index, :before)
|
84
|
-
|
85
|
-
middlewares.insert(index, middleware)
|
76
|
+
middlewares.insert(index, build_middleware(klass, args, block))
|
86
77
|
end
|
87
78
|
|
88
79
|
alias_method :insert_before, :insert
|
@@ -99,26 +90,27 @@ module ActionDispatch
|
|
99
90
|
end
|
100
91
|
|
101
92
|
def delete(target)
|
102
|
-
middlewares.
|
93
|
+
middlewares.delete_if { |m| m.klass == target }
|
103
94
|
end
|
104
95
|
|
105
|
-
def use(*args, &block)
|
106
|
-
|
107
|
-
middlewares.push(middleware)
|
96
|
+
def use(klass, *args, &block)
|
97
|
+
middlewares.push(build_middleware(klass, args, block))
|
108
98
|
end
|
109
99
|
|
110
100
|
def build(app = nil, &block)
|
111
|
-
app
|
112
|
-
raise "MiddlewareStack#build requires an app" unless app
|
113
|
-
middlewares.reverse.inject(app) { |a, e| e.build(a) }
|
101
|
+
middlewares.freeze.reverse.inject(app || block) { |a, e| e.build(a) }
|
114
102
|
end
|
115
103
|
|
116
|
-
|
104
|
+
private
|
117
105
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
106
|
+
def assert_index(index, where)
|
107
|
+
i = index.is_a?(Integer) ? index : middlewares.index { |m| m.klass == index }
|
108
|
+
raise "No such middleware to insert #{where}: #{index.inspect}" unless i
|
109
|
+
i
|
110
|
+
end
|
111
|
+
|
112
|
+
def build_middleware(klass, args, block)
|
113
|
+
Middleware.new(klass, args, block)
|
114
|
+
end
|
123
115
|
end
|
124
116
|
end
|
@@ -1,86 +1,130 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rack/utils"
|
4
|
+
require "active_support/core_ext/uri"
|
2
5
|
|
3
6
|
module ActionDispatch
|
7
|
+
# This middleware returns a file's contents from disk in the body response.
|
8
|
+
# When initialized, it can accept optional HTTP headers, which will be set
|
9
|
+
# when a response containing a file's contents is delivered.
|
10
|
+
#
|
11
|
+
# This middleware will render the file specified in <tt>env["PATH_INFO"]</tt>
|
12
|
+
# where the base path is in the +root+ directory. For example, if the +root+
|
13
|
+
# is set to +public/+, then a request with <tt>env["PATH_INFO"]</tt> of
|
14
|
+
# +assets/application.js+ will return a response with the contents of a file
|
15
|
+
# located at +public/assets/application.js+ if the file exists. If the file
|
16
|
+
# does not exist, a 404 "File not Found" response will be returned.
|
4
17
|
class FileHandler
|
5
|
-
def initialize(root,
|
6
|
-
@root = root.chomp(
|
7
|
-
@compiled_root = /^#{Regexp.escape(root)}/
|
8
|
-
headers = cache_control && { 'Cache-Control' => cache_control }
|
18
|
+
def initialize(root, index: "index", headers: {})
|
19
|
+
@root = root.chomp("/").b
|
9
20
|
@file_server = ::Rack::File.new(@root, headers)
|
21
|
+
@index = index
|
10
22
|
end
|
11
23
|
|
24
|
+
# Takes a path to a file. If the file is found, has valid encoding, and has
|
25
|
+
# correct read permissions, the return value is a URI-escaped string
|
26
|
+
# representing the filename. Otherwise, false is returned.
|
27
|
+
#
|
28
|
+
# Used by the +Static+ class to check the existence of a valid file
|
29
|
+
# in the server's +public/+ directory (see Static#call).
|
12
30
|
def match?(path)
|
13
|
-
path = path
|
14
|
-
|
15
|
-
|
16
|
-
|
31
|
+
path = ::Rack::Utils.unescape_path path
|
32
|
+
return false unless ::Rack::Utils.valid_path? path
|
33
|
+
path = ::Rack::Utils.clean_path_info path
|
34
|
+
|
35
|
+
paths = [path, "#{path}#{ext}", "#{path}/#{@index}#{ext}"]
|
36
|
+
|
37
|
+
if match = paths.detect { |p|
|
38
|
+
path = File.join(@root, p.b)
|
39
|
+
begin
|
40
|
+
File.file?(path) && File.readable?(path)
|
41
|
+
rescue SystemCallError
|
42
|
+
false
|
43
|
+
end
|
17
44
|
|
18
|
-
|
19
|
-
|
20
|
-
if match
|
21
|
-
match.sub!(@compiled_root, '')
|
22
|
-
::Rack::Utils.escape(match)
|
45
|
+
}
|
46
|
+
return ::Rack::Utils.escape_path(match).b
|
23
47
|
end
|
24
48
|
end
|
25
49
|
|
26
50
|
def call(env)
|
27
|
-
|
51
|
+
serve(Rack::Request.new(env))
|
28
52
|
end
|
29
53
|
|
30
|
-
def
|
31
|
-
|
32
|
-
|
33
|
-
|
54
|
+
def serve(request)
|
55
|
+
path = request.path_info
|
56
|
+
gzip_path = gzip_file_path(path)
|
57
|
+
|
58
|
+
if gzip_path && gzip_encoding_accepted?(request)
|
59
|
+
request.path_info = gzip_path
|
60
|
+
status, headers, body = @file_server.call(request.env)
|
61
|
+
if status == 304
|
62
|
+
return [status, headers, body]
|
63
|
+
end
|
64
|
+
headers["Content-Encoding"] = "gzip"
|
65
|
+
headers["Content-Type"] = content_type(path)
|
66
|
+
else
|
67
|
+
status, headers, body = @file_server.call(request.env)
|
34
68
|
end
|
35
|
-
end
|
36
69
|
|
37
|
-
|
38
|
-
URI.parser.unescape(path)
|
39
|
-
end
|
70
|
+
headers["Vary"] = "Accept-Encoding" if gzip_path
|
40
71
|
|
41
|
-
|
42
|
-
|
43
|
-
|
72
|
+
return [status, headers, body]
|
73
|
+
ensure
|
74
|
+
request.path_info = path
|
44
75
|
end
|
45
76
|
|
46
77
|
private
|
78
|
+
def ext
|
79
|
+
::ActionController::Base.default_static_extension
|
80
|
+
end
|
47
81
|
|
48
|
-
|
49
|
-
|
50
|
-
def clean_path_info(path_info)
|
51
|
-
path_info.force_encoding('binary') if path_info.respond_to? :force_encoding
|
52
|
-
parts = path_info.split PATH_SEPS
|
53
|
-
|
54
|
-
clean = []
|
55
|
-
|
56
|
-
parts.each do |part|
|
57
|
-
next if part.empty? || part == '.'
|
58
|
-
part == '..' ? clean.pop : clean << part
|
82
|
+
def content_type(path)
|
83
|
+
::Rack::Mime.mime_type(::File.extname(path), "text/plain".freeze)
|
59
84
|
end
|
60
85
|
|
61
|
-
|
86
|
+
def gzip_encoding_accepted?(request)
|
87
|
+
request.accept_encoding.any? { |enc, quality| enc =~ /\bgzip\b/i }
|
88
|
+
end
|
62
89
|
|
63
|
-
|
64
|
-
|
90
|
+
def gzip_file_path(path)
|
91
|
+
can_gzip_mime = content_type(path) =~ /\A(?:text\/|application\/javascript)/
|
92
|
+
gzip_path = "#{path}.gz"
|
93
|
+
if can_gzip_mime && File.exist?(File.join(@root, ::Rack::Utils.unescape_path(gzip_path).b))
|
94
|
+
gzip_path.b
|
95
|
+
else
|
96
|
+
false
|
97
|
+
end
|
98
|
+
end
|
65
99
|
end
|
66
100
|
|
101
|
+
# This middleware will attempt to return the contents of a file's body from
|
102
|
+
# disk in the response. If a file is not found on disk, the request will be
|
103
|
+
# delegated to the application stack. This middleware is commonly initialized
|
104
|
+
# to serve assets from a server's +public/+ directory.
|
105
|
+
#
|
106
|
+
# This middleware verifies the path to ensure that only files
|
107
|
+
# living in the root directory can be rendered. A request cannot
|
108
|
+
# produce a directory traversal using this middleware. Only 'GET' and 'HEAD'
|
109
|
+
# requests will result in a file being returned.
|
67
110
|
class Static
|
68
|
-
def initialize(app, path,
|
111
|
+
def initialize(app, path, index: "index", headers: {})
|
69
112
|
@app = app
|
70
|
-
@file_handler = FileHandler.new(path,
|
113
|
+
@file_handler = FileHandler.new(path, index: index, headers: headers)
|
71
114
|
end
|
72
115
|
|
73
116
|
def call(env)
|
74
|
-
|
75
|
-
|
76
|
-
|
117
|
+
req = Rack::Request.new env
|
118
|
+
|
119
|
+
if req.get? || req.head?
|
120
|
+
path = req.path_info.chomp("/".freeze)
|
77
121
|
if match = @file_handler.match?(path)
|
78
|
-
|
79
|
-
return @file_handler.
|
122
|
+
req.path_info = match
|
123
|
+
return @file_handler.serve(req)
|
80
124
|
end
|
81
125
|
end
|
82
126
|
|
83
|
-
@app.call(env)
|
127
|
+
@app.call(req.env)
|
84
128
|
end
|
85
129
|
end
|
86
130
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
<% unless @exception.blamed_files.blank? %>
|
2
|
+
<% if (hide = @exception.blamed_files.length > 8) %>
|
3
|
+
<a href="#" onclick="return toggleTrace()">Toggle blamed files</a>
|
4
|
+
<% end %>
|
5
|
+
<pre id="blame_trace" <%='style="display:none"' if hide %>><code><%= @exception.describe_blame %></code></pre>
|
6
|
+
<% end %>
|
7
|
+
|
8
|
+
<h2 style="margin-top: 30px">Request</h2>
|
9
|
+
<p><b>Parameters</b>:</p> <pre><%= debug_params(@request.filtered_parameters) %></pre>
|
10
|
+
|
11
|
+
<div class="details">
|
12
|
+
<div class="summary"><a href="#" onclick="return toggleSessionDump()">Toggle session dump</a></div>
|
13
|
+
<div id="session_dump" style="display:none"><pre><%= debug_hash @request.session %></pre></div>
|
14
|
+
</div>
|
15
|
+
|
16
|
+
<div class="details">
|
17
|
+
<div class="summary"><a href="#" onclick="return toggleEnvDump()">Toggle env dump</a></div>
|
18
|
+
<div id="env_dump" style="display:none"><pre><%= debug_hash @request.env.slice(*@request.class::ENV_METHODS) %></pre></div>
|
19
|
+
</div>
|
20
|
+
|
21
|
+
<h2 style="margin-top: 30px">Response</h2>
|
22
|
+
<p><b>Headers</b>:</p> <pre><%= debug_headers(defined?(@response) ? @response.headers : {}) %></pre>
|
@@ -0,0 +1,23 @@
|
|
1
|
+
<%
|
2
|
+
clean_params = @request.filtered_parameters.clone
|
3
|
+
clean_params.delete("action")
|
4
|
+
clean_params.delete("controller")
|
5
|
+
|
6
|
+
request_dump = clean_params.empty? ? 'None' : clean_params.inspect.gsub(',', ",\n")
|
7
|
+
|
8
|
+
def debug_hash(object)
|
9
|
+
object.to_hash.sort_by { |k, _| k.to_s }.map { |k, v| "#{k}: #{v.inspect rescue $!.message}" }.join("\n")
|
10
|
+
end unless self.class.method_defined?(:debug_hash)
|
11
|
+
%>
|
12
|
+
|
13
|
+
Request parameters
|
14
|
+
<%= request_dump %>
|
15
|
+
|
16
|
+
Session dump
|
17
|
+
<%= debug_hash @request.session %>
|
18
|
+
|
19
|
+
Env dump
|
20
|
+
<%= debug_hash @request.env.slice(*@request.class::ENV_METHODS) %>
|
21
|
+
|
22
|
+
Response headers
|
23
|
+
<%= defined?(@response) ? @response.headers.inspect.gsub(',', ",\n") : 'None' %>
|