actionpack 5.2.1 → 7.0.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 +4 -4
- data/CHANGELOG.md +264 -220
- data/MIT-LICENSE +1 -1
- data/README.rdoc +6 -6
- data/lib/abstract_controller/asset_paths.rb +1 -1
- data/lib/abstract_controller/base.rb +24 -4
- data/lib/abstract_controller/caching/fragments.rb +8 -24
- data/lib/abstract_controller/caching.rb +2 -2
- data/lib/abstract_controller/callbacks.rb +34 -8
- data/lib/abstract_controller/collector.rb +5 -4
- data/lib/abstract_controller/error.rb +1 -1
- data/lib/abstract_controller/helpers.rb +107 -90
- data/lib/abstract_controller/logger.rb +1 -1
- data/lib/abstract_controller/railties/routes_helpers.rb +19 -1
- data/lib/abstract_controller/rendering.rb +9 -9
- data/lib/abstract_controller/translation.rb +12 -5
- data/lib/abstract_controller/url_for.rb +4 -6
- data/lib/abstract_controller.rb +2 -0
- data/lib/action_controller/api.rb +5 -4
- data/lib/action_controller/base.rb +6 -9
- data/lib/action_controller/caching.rb +1 -3
- data/lib/action_controller/log_subscriber.rb +13 -9
- data/lib/action_controller/metal/basic_implicit_render.rb +1 -1
- data/lib/action_controller/metal/conditional_get.rb +57 -6
- data/lib/action_controller/metal/content_security_policy.rb +2 -3
- data/lib/action_controller/metal/cookies.rb +4 -2
- data/lib/action_controller/metal/data_streaming.rb +9 -18
- data/lib/action_controller/metal/default_headers.rb +17 -0
- data/lib/action_controller/metal/etag_with_template_digest.rb +4 -6
- data/lib/action_controller/metal/exceptions.rb +55 -12
- data/lib/action_controller/metal/flash.rb +10 -6
- data/lib/action_controller/metal/head.rb +7 -4
- data/lib/action_controller/metal/helpers.rb +15 -6
- data/lib/action_controller/metal/http_authentication.rb +41 -39
- data/lib/action_controller/metal/implicit_render.rb +5 -15
- data/lib/action_controller/metal/instrumentation.rb +59 -55
- data/lib/action_controller/metal/live.rb +80 -33
- data/lib/action_controller/metal/logging.rb +20 -0
- data/lib/action_controller/metal/mime_responds.rb +22 -7
- data/lib/action_controller/metal/parameter_encoding.rb +35 -4
- data/lib/action_controller/metal/params_wrapper.rb +50 -31
- data/lib/action_controller/metal/permissions_policy.rb +46 -0
- data/lib/action_controller/metal/redirecting.rb +93 -23
- data/lib/action_controller/metal/renderers.rb +4 -4
- data/lib/action_controller/metal/rendering.rb +14 -9
- data/lib/action_controller/metal/request_forgery_protection.rb +160 -58
- data/lib/action_controller/metal/rescue.rb +2 -2
- data/lib/action_controller/metal/streaming.rb +1 -4
- data/lib/action_controller/metal/strong_parameters.rb +236 -88
- data/lib/action_controller/metal/testing.rb +9 -2
- data/lib/action_controller/metal/url_for.rb +1 -1
- data/lib/action_controller/metal.rb +16 -17
- data/lib/action_controller/railtie.rb +49 -6
- data/lib/action_controller/railties/helpers.rb +1 -1
- data/lib/action_controller/renderer.rb +37 -13
- data/lib/action_controller/template_assertions.rb +1 -1
- data/lib/action_controller/test_case.rb +98 -68
- data/lib/action_controller.rb +4 -5
- data/lib/action_dispatch/http/cache.rb +45 -32
- data/lib/action_dispatch/http/content_disposition.rb +45 -0
- data/lib/action_dispatch/http/content_security_policy.rb +69 -56
- data/lib/action_dispatch/http/filter_parameters.rb +14 -8
- data/lib/action_dispatch/http/filter_redirect.rb +2 -3
- data/lib/action_dispatch/http/headers.rb +4 -4
- data/lib/action_dispatch/http/mime_negotiation.rb +44 -16
- data/lib/action_dispatch/http/mime_type.rb +47 -30
- data/lib/action_dispatch/http/parameters.rb +18 -27
- data/lib/action_dispatch/http/permissions_policy.rb +173 -0
- data/lib/action_dispatch/http/request.rb +49 -35
- data/lib/action_dispatch/http/response.rb +34 -26
- data/lib/action_dispatch/http/upload.rb +9 -1
- data/lib/action_dispatch/http/url.rb +86 -94
- data/lib/action_dispatch/journey/formatter.rb +55 -31
- data/lib/action_dispatch/journey/gtg/builder.rb +30 -46
- data/lib/action_dispatch/journey/gtg/simulator.rb +15 -8
- data/lib/action_dispatch/journey/gtg/transition_table.rb +78 -21
- data/lib/action_dispatch/journey/nfa/dot.rb +0 -11
- data/lib/action_dispatch/journey/nodes/node.rb +83 -16
- data/lib/action_dispatch/journey/parser.rb +13 -13
- data/lib/action_dispatch/journey/parser.y +1 -1
- data/lib/action_dispatch/journey/path/pattern.rb +42 -34
- data/lib/action_dispatch/journey/route.rb +14 -31
- data/lib/action_dispatch/journey/router/utils.rb +16 -14
- data/lib/action_dispatch/journey/router.rb +27 -35
- data/lib/action_dispatch/journey/routes.rb +3 -5
- data/lib/action_dispatch/journey/scanner.rb +10 -4
- data/lib/action_dispatch/journey/visitors.rb +1 -4
- data/lib/action_dispatch/journey/visualizer/fsm.js +49 -24
- data/lib/action_dispatch/journey/visualizer/index.html.erb +1 -1
- data/lib/action_dispatch/journey.rb +0 -2
- data/lib/action_dispatch/middleware/actionable_exceptions.rb +45 -0
- data/lib/action_dispatch/middleware/callbacks.rb +2 -4
- data/lib/action_dispatch/middleware/cookies.rb +136 -113
- data/lib/action_dispatch/middleware/debug_exceptions.rb +47 -68
- data/lib/action_dispatch/middleware/debug_locks.rb +8 -8
- data/lib/action_dispatch/middleware/debug_view.rb +66 -0
- data/lib/action_dispatch/middleware/exception_wrapper.rb +79 -30
- data/lib/action_dispatch/middleware/executor.rb +4 -1
- data/lib/action_dispatch/middleware/flash.rb +10 -12
- data/lib/action_dispatch/middleware/host_authorization.rb +159 -0
- data/lib/action_dispatch/middleware/public_exceptions.rb +6 -3
- data/lib/action_dispatch/middleware/remote_ip.rb +30 -20
- data/lib/action_dispatch/middleware/request_id.rb +5 -6
- data/lib/action_dispatch/middleware/server_timing.rb +33 -0
- data/lib/action_dispatch/middleware/session/abstract_store.rb +16 -3
- data/lib/action_dispatch/middleware/session/cache_store.rb +11 -6
- data/lib/action_dispatch/middleware/session/cookie_store.rb +24 -19
- data/lib/action_dispatch/middleware/show_exceptions.rb +20 -11
- data/lib/action_dispatch/middleware/ssl.rb +20 -15
- data/lib/action_dispatch/middleware/stack.rb +79 -7
- data/lib/action_dispatch/middleware/static.rb +150 -94
- data/lib/action_dispatch/middleware/templates/rescues/_actions.html.erb +13 -0
- data/lib/action_dispatch/middleware/templates/rescues/_actions.text.erb +0 -0
- data/lib/action_dispatch/middleware/templates/rescues/_message_and_suggestions.html.erb +22 -0
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +6 -11
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +4 -2
- data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +46 -36
- data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +8 -0
- data/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb +7 -0
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +25 -6
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +9 -6
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +4 -1
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +121 -15
- data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +19 -0
- data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.text.erb +3 -0
- data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +5 -5
- data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +4 -4
- data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +5 -5
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +4 -4
- data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +16 -2
- data/lib/action_dispatch/railtie.rb +16 -4
- data/lib/action_dispatch/request/session.rb +59 -22
- data/lib/action_dispatch/request/utils.rb +28 -2
- data/lib/action_dispatch/routing/inspector.rb +102 -54
- data/lib/action_dispatch/routing/mapper.rb +184 -156
- data/lib/action_dispatch/routing/polymorphic_routes.rb +21 -19
- data/lib/action_dispatch/routing/redirection.rb +4 -6
- data/lib/action_dispatch/routing/route_set.rb +83 -73
- data/lib/action_dispatch/routing/routes_proxy.rb +1 -1
- data/lib/action_dispatch/routing/url_for.rb +2 -3
- data/lib/action_dispatch/routing.rb +23 -22
- data/lib/action_dispatch/system_test_case.rb +65 -16
- data/lib/action_dispatch/system_testing/browser.rb +43 -16
- data/lib/action_dispatch/system_testing/driver.rb +42 -10
- data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +58 -12
- data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +3 -10
- data/lib/action_dispatch/testing/assertion_response.rb +0 -1
- data/lib/action_dispatch/testing/assertions/response.rb +4 -7
- data/lib/action_dispatch/testing/assertions/routing.rb +20 -8
- data/lib/action_dispatch/testing/assertions.rb +3 -6
- data/lib/action_dispatch/testing/integration.rb +61 -30
- data/lib/action_dispatch/testing/request_encoder.rb +2 -2
- data/lib/action_dispatch/testing/test_process.rb +8 -6
- data/lib/action_dispatch/testing/test_request.rb +3 -3
- data/lib/action_dispatch/testing/test_response.rb +4 -32
- data/lib/action_dispatch.rb +15 -7
- data/lib/action_pack/gem_version.rb +4 -4
- data/lib/action_pack.rb +1 -1
- metadata +44 -25
- data/lib/action_controller/metal/force_ssl.rb +0 -99
- data/lib/action_dispatch/http/parameter_filter.rb +0 -86
- data/lib/action_dispatch/journey/nfa/builder.rb +0 -78
- data/lib/action_dispatch/journey/nfa/simulator.rb +0 -49
- data/lib/action_dispatch/journey/nfa/transition_table.rb +0 -120
- data/lib/action_dispatch/system_testing/test_helpers/undef_methods.rb +0 -26
@@ -1,59 +1,26 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "action_dispatch/http/request"
|
4
3
|
require "action_dispatch/middleware/exception_wrapper"
|
5
4
|
require "action_dispatch/routing/inspector"
|
6
|
-
require "action_view"
|
7
|
-
require "action_view/base"
|
8
5
|
|
9
|
-
require "
|
6
|
+
require "action_view"
|
10
7
|
|
11
8
|
module ActionDispatch
|
12
9
|
# This middleware is responsible for logging exceptions and
|
13
10
|
# showing a debugging page in case the request is local.
|
14
11
|
class DebugExceptions
|
15
|
-
|
16
|
-
|
17
|
-
class DebugView < ActionView::Base
|
18
|
-
def debug_params(params)
|
19
|
-
clean_params = params.clone
|
20
|
-
clean_params.delete("action")
|
21
|
-
clean_params.delete("controller")
|
12
|
+
cattr_reader :interceptors, instance_accessor: false, default: []
|
22
13
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
PP.pp(clean_params, "".dup, 200)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
def debug_headers(headers)
|
31
|
-
if headers.present?
|
32
|
-
headers.inspect.gsub(",", ",\n")
|
33
|
-
else
|
34
|
-
"None"
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
def debug_hash(object)
|
39
|
-
object.to_hash.sort_by { |k, _| k.to_s }.map { |k, v| "#{k}: #{v.inspect rescue $!.message}" }.join("\n")
|
40
|
-
end
|
41
|
-
|
42
|
-
def render(*)
|
43
|
-
logger = ActionView::Base.logger
|
44
|
-
|
45
|
-
if logger && logger.respond_to?(:silence)
|
46
|
-
logger.silence { super }
|
47
|
-
else
|
48
|
-
super
|
49
|
-
end
|
50
|
-
end
|
14
|
+
def self.register_interceptor(object = nil, &block)
|
15
|
+
interceptor = object || block
|
16
|
+
interceptors << interceptor
|
51
17
|
end
|
52
18
|
|
53
|
-
def initialize(app, routes_app = nil, response_format = :default)
|
19
|
+
def initialize(app, routes_app = nil, response_format = :default, interceptors = self.class.interceptors)
|
54
20
|
@app = app
|
55
21
|
@routes_app = routes_app
|
56
22
|
@response_format = response_format
|
23
|
+
@interceptors = interceptors
|
57
24
|
end
|
58
25
|
|
59
26
|
def call(env)
|
@@ -67,11 +34,22 @@ module ActionDispatch
|
|
67
34
|
|
68
35
|
response
|
69
36
|
rescue Exception => exception
|
37
|
+
invoke_interceptors(request, exception)
|
70
38
|
raise exception unless request.show_exceptions?
|
71
39
|
render_exception(request, exception)
|
72
40
|
end
|
73
41
|
|
74
42
|
private
|
43
|
+
def invoke_interceptors(request, exception)
|
44
|
+
backtrace_cleaner = request.get_header("action_dispatch.backtrace_cleaner")
|
45
|
+
wrapper = ExceptionWrapper.new(backtrace_cleaner, exception)
|
46
|
+
|
47
|
+
@interceptors.each do |interceptor|
|
48
|
+
interceptor.call(request, exception)
|
49
|
+
rescue Exception
|
50
|
+
log_error(request, wrapper)
|
51
|
+
end
|
52
|
+
end
|
75
53
|
|
76
54
|
def render_exception(request, exception)
|
77
55
|
backtrace_cleaner = request.get_header("action_dispatch.backtrace_cleaner")
|
@@ -79,7 +57,11 @@ module ActionDispatch
|
|
79
57
|
log_error(request, wrapper)
|
80
58
|
|
81
59
|
if request.get_header("action_dispatch.show_detailed_exceptions")
|
82
|
-
|
60
|
+
begin
|
61
|
+
content_type = request.formats.first
|
62
|
+
rescue ActionDispatch::Http::MimeNegotiation::InvalidType
|
63
|
+
content_type = Mime[:text]
|
64
|
+
end
|
83
65
|
|
84
66
|
if api_request?(content_type)
|
85
67
|
render_for_api_request(content_type, wrapper)
|
@@ -130,23 +112,13 @@ module ActionDispatch
|
|
130
112
|
end
|
131
113
|
|
132
114
|
def create_template(request, wrapper)
|
133
|
-
|
134
|
-
|
135
|
-
trace_to_show = "Application Trace"
|
136
|
-
if traces[trace_to_show].empty? && wrapper.rescue_template != "routing_error"
|
137
|
-
trace_to_show = "Full Trace"
|
138
|
-
end
|
139
|
-
|
140
|
-
if source_to_show = traces[trace_to_show].first
|
141
|
-
source_to_show_id = source_to_show[:id]
|
142
|
-
end
|
143
|
-
|
144
|
-
DebugView.new([RESCUES_TEMPLATE_PATH],
|
115
|
+
DebugView.new(
|
145
116
|
request: request,
|
117
|
+
exception_wrapper: wrapper,
|
146
118
|
exception: wrapper.exception,
|
147
|
-
traces: traces,
|
148
|
-
show_source_idx: source_to_show_id,
|
149
|
-
trace_to_show: trace_to_show,
|
119
|
+
traces: wrapper.traces,
|
120
|
+
show_source_idx: wrapper.source_to_show_id,
|
121
|
+
trace_to_show: wrapper.trace_to_show,
|
150
122
|
routes_inspector: routes_inspector(wrapper.exception),
|
151
123
|
source_extracts: wrapper.source_extracts,
|
152
124
|
line_number: wrapper.line_number,
|
@@ -160,27 +132,30 @@ module ActionDispatch
|
|
160
132
|
|
161
133
|
def log_error(request, wrapper)
|
162
134
|
logger = logger(request)
|
135
|
+
|
163
136
|
return unless logger
|
137
|
+
return if !log_rescued_responses?(request) && wrapper.rescue_response?
|
164
138
|
|
165
139
|
exception = wrapper.exception
|
140
|
+
trace = wrapper.exception_trace
|
166
141
|
|
167
|
-
|
168
|
-
|
142
|
+
message = []
|
143
|
+
message << " "
|
144
|
+
message << "#{exception.class} (#{exception.message}):"
|
145
|
+
message.concat(exception.annotated_source_code) if exception.respond_to?(:annotated_source_code)
|
146
|
+
message << " "
|
147
|
+
message.concat(trace)
|
169
148
|
|
170
|
-
|
171
|
-
logger.fatal " "
|
172
|
-
logger.fatal "#{exception.class} (#{exception.message}):"
|
173
|
-
log_array logger, exception.annoted_source_code if exception.respond_to?(:annoted_source_code)
|
174
|
-
logger.fatal " "
|
175
|
-
log_array logger, trace
|
176
|
-
end
|
149
|
+
log_array(logger, message)
|
177
150
|
end
|
178
151
|
|
179
|
-
def log_array(logger,
|
152
|
+
def log_array(logger, lines)
|
153
|
+
return if lines.empty?
|
154
|
+
|
180
155
|
if logger.formatter && logger.formatter.respond_to?(:tags_text)
|
181
|
-
logger.fatal
|
156
|
+
logger.fatal lines.join("\n#{logger.formatter.tags_text}")
|
182
157
|
else
|
183
|
-
logger.fatal
|
158
|
+
logger.fatal lines.join("\n")
|
184
159
|
end
|
185
160
|
end
|
186
161
|
|
@@ -201,5 +176,9 @@ module ActionDispatch
|
|
201
176
|
def api_request?(content_type)
|
202
177
|
@response_format == :api && !content_type.html?
|
203
178
|
end
|
179
|
+
|
180
|
+
def log_rescued_responses?(request)
|
181
|
+
request.get_header("action_dispatch.log_rescued_responses")
|
182
|
+
end
|
204
183
|
end
|
205
184
|
end
|
@@ -9,9 +9,9 @@ module ActionDispatch
|
|
9
9
|
# config.middleware.insert_before Rack::Sendfile, ActionDispatch::DebugLocks
|
10
10
|
#
|
11
11
|
# After restarting the application and re-triggering the deadlock condition,
|
12
|
-
# <tt>/rails/locks</tt> will show a summary of all threads currently
|
13
|
-
# the interlock, which lock level they are holding or awaiting, and
|
14
|
-
# current backtrace.
|
12
|
+
# the route <tt>/rails/locks</tt> will show a summary of all threads currently
|
13
|
+
# known to the interlock, which lock level they are holding or awaiting, and
|
14
|
+
# their current backtrace.
|
15
15
|
#
|
16
16
|
# Generally a deadlock will be caused by the interlock conflicting with some
|
17
17
|
# other external lock or blocking I/O call. These cannot be automatically
|
@@ -32,7 +32,7 @@ module ActionDispatch
|
|
32
32
|
req = ActionDispatch::Request.new env
|
33
33
|
|
34
34
|
if req.get?
|
35
|
-
path = req.path_info.chomp("/"
|
35
|
+
path = req.path_info.chomp("/")
|
36
36
|
if path == @path
|
37
37
|
return render_details(req)
|
38
38
|
end
|
@@ -63,19 +63,19 @@ module ActionDispatch
|
|
63
63
|
|
64
64
|
str = threads.map do |thread, info|
|
65
65
|
if info[:exclusive]
|
66
|
-
lock_state = "Exclusive"
|
66
|
+
lock_state = +"Exclusive"
|
67
67
|
elsif info[:sharing] > 0
|
68
|
-
lock_state = "Sharing"
|
68
|
+
lock_state = +"Sharing"
|
69
69
|
lock_state << " x#{info[:sharing]}" if info[:sharing] > 1
|
70
70
|
else
|
71
|
-
lock_state = "No lock"
|
71
|
+
lock_state = +"No lock"
|
72
72
|
end
|
73
73
|
|
74
74
|
if info[:waiting]
|
75
75
|
lock_state << " (yielded share)"
|
76
76
|
end
|
77
77
|
|
78
|
-
msg = "Thread #{info[:index]} [0x#{thread.__id__.to_s(16)} #{thread.status || 'dead'}] #{lock_state}\n"
|
78
|
+
msg = +"Thread #{info[:index]} [0x#{thread.__id__.to_s(16)} #{thread.status || 'dead'}] #{lock_state}\n"
|
79
79
|
|
80
80
|
if info[:sleeper]
|
81
81
|
msg << " Waiting in #{info[:sleeper]}"
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "pp"
|
4
|
+
|
5
|
+
require "action_view"
|
6
|
+
require "action_view/base"
|
7
|
+
|
8
|
+
module ActionDispatch
|
9
|
+
class DebugView < ActionView::Base # :nodoc:
|
10
|
+
RESCUES_TEMPLATE_PATH = File.expand_path("templates", __dir__)
|
11
|
+
|
12
|
+
def initialize(assigns)
|
13
|
+
paths = [RESCUES_TEMPLATE_PATH]
|
14
|
+
lookup_context = ActionView::LookupContext.new(paths)
|
15
|
+
super(lookup_context, assigns, nil)
|
16
|
+
end
|
17
|
+
|
18
|
+
def compiled_method_container
|
19
|
+
self.class
|
20
|
+
end
|
21
|
+
|
22
|
+
def debug_params(params)
|
23
|
+
clean_params = params.clone
|
24
|
+
clean_params.delete("action")
|
25
|
+
clean_params.delete("controller")
|
26
|
+
|
27
|
+
if clean_params.empty?
|
28
|
+
"None"
|
29
|
+
else
|
30
|
+
PP.pp(clean_params, +"", 200)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def debug_headers(headers)
|
35
|
+
if headers.present?
|
36
|
+
headers.inspect.gsub(",", ",\n")
|
37
|
+
else
|
38
|
+
"None"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def debug_hash(object)
|
43
|
+
object.to_hash.sort_by { |k, _| k.to_s }.map { |k, v| "#{k}: #{v.inspect rescue $!.message}" }.join("\n")
|
44
|
+
end
|
45
|
+
|
46
|
+
def render(*)
|
47
|
+
logger = ActionView::Base.logger
|
48
|
+
|
49
|
+
if logger && logger.respond_to?(:silence)
|
50
|
+
logger.silence { super }
|
51
|
+
else
|
52
|
+
super
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def protect_against_forgery?
|
57
|
+
false
|
58
|
+
end
|
59
|
+
|
60
|
+
def params_valid?
|
61
|
+
@request.parameters
|
62
|
+
rescue ActionController::BadRequest
|
63
|
+
false
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -6,44 +6,72 @@ require "rack/utils"
|
|
6
6
|
module ActionDispatch
|
7
7
|
class ExceptionWrapper
|
8
8
|
cattr_accessor :rescue_responses, default: Hash.new(:internal_server_error).merge!(
|
9
|
-
"ActionController::RoutingError"
|
10
|
-
"AbstractController::ActionNotFound"
|
11
|
-
"ActionController::MethodNotAllowed"
|
12
|
-
"ActionController::UnknownHttpMethod"
|
13
|
-
"ActionController::NotImplemented"
|
14
|
-
"ActionController::UnknownFormat"
|
15
|
-
"
|
16
|
-
"ActionController::
|
17
|
-
"
|
18
|
-
"ActionController::
|
19
|
-
"
|
20
|
-
"
|
21
|
-
"
|
9
|
+
"ActionController::RoutingError" => :not_found,
|
10
|
+
"AbstractController::ActionNotFound" => :not_found,
|
11
|
+
"ActionController::MethodNotAllowed" => :method_not_allowed,
|
12
|
+
"ActionController::UnknownHttpMethod" => :method_not_allowed,
|
13
|
+
"ActionController::NotImplemented" => :not_implemented,
|
14
|
+
"ActionController::UnknownFormat" => :not_acceptable,
|
15
|
+
"ActionDispatch::Http::MimeNegotiation::InvalidType" => :not_acceptable,
|
16
|
+
"ActionController::MissingExactTemplate" => :not_acceptable,
|
17
|
+
"ActionController::InvalidAuthenticityToken" => :unprocessable_entity,
|
18
|
+
"ActionController::InvalidCrossOriginRequest" => :unprocessable_entity,
|
19
|
+
"ActionDispatch::Http::Parameters::ParseError" => :bad_request,
|
20
|
+
"ActionController::BadRequest" => :bad_request,
|
21
|
+
"ActionController::ParameterMissing" => :bad_request,
|
22
|
+
"Rack::QueryParser::ParameterTypeError" => :bad_request,
|
23
|
+
"Rack::QueryParser::InvalidParameterError" => :bad_request
|
22
24
|
)
|
23
25
|
|
24
26
|
cattr_accessor :rescue_templates, default: Hash.new("diagnostics").merge!(
|
25
|
-
"ActionView::MissingTemplate"
|
26
|
-
"ActionController::RoutingError"
|
27
|
-
"AbstractController::ActionNotFound"
|
28
|
-
"ActiveRecord::StatementInvalid"
|
29
|
-
"ActionView::Template::Error"
|
27
|
+
"ActionView::MissingTemplate" => "missing_template",
|
28
|
+
"ActionController::RoutingError" => "routing_error",
|
29
|
+
"AbstractController::ActionNotFound" => "unknown_action",
|
30
|
+
"ActiveRecord::StatementInvalid" => "invalid_statement",
|
31
|
+
"ActionView::Template::Error" => "template_error",
|
32
|
+
"ActionController::MissingExactTemplate" => "missing_exact_template",
|
30
33
|
)
|
31
34
|
|
32
|
-
|
35
|
+
cattr_accessor :wrapper_exceptions, default: [
|
36
|
+
"ActionView::Template::Error"
|
37
|
+
]
|
38
|
+
|
39
|
+
cattr_accessor :silent_exceptions, default: [
|
40
|
+
"ActionController::RoutingError",
|
41
|
+
"ActionDispatch::Http::MimeNegotiation::InvalidType"
|
42
|
+
]
|
43
|
+
|
44
|
+
attr_reader :backtrace_cleaner, :exception, :wrapped_causes, :line_number, :file
|
33
45
|
|
34
46
|
def initialize(backtrace_cleaner, exception)
|
35
47
|
@backtrace_cleaner = backtrace_cleaner
|
36
|
-
@exception =
|
48
|
+
@exception = exception
|
49
|
+
@exception_class_name = @exception.class.name
|
50
|
+
@wrapped_causes = wrapped_causes_for(exception, backtrace_cleaner)
|
37
51
|
|
38
52
|
expand_backtrace if exception.is_a?(SyntaxError) || exception.cause.is_a?(SyntaxError)
|
39
53
|
end
|
40
54
|
|
55
|
+
def unwrapped_exception
|
56
|
+
if wrapper_exceptions.include?(@exception_class_name)
|
57
|
+
exception.cause
|
58
|
+
else
|
59
|
+
exception
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
41
63
|
def rescue_template
|
42
|
-
@@rescue_templates[@
|
64
|
+
@@rescue_templates[@exception_class_name]
|
43
65
|
end
|
44
66
|
|
45
67
|
def status_code
|
46
|
-
self.class.status_code_for_exception(
|
68
|
+
self.class.status_code_for_exception(unwrapped_exception.class.name)
|
69
|
+
end
|
70
|
+
|
71
|
+
def exception_trace
|
72
|
+
trace = application_trace
|
73
|
+
trace = framework_trace if trace.empty? && !silent_exceptions.include?(@exception_class_name)
|
74
|
+
trace
|
47
75
|
end
|
48
76
|
|
49
77
|
def application_trace
|
@@ -64,7 +92,11 @@ module ActionDispatch
|
|
64
92
|
full_trace_with_ids = []
|
65
93
|
|
66
94
|
full_trace.each_with_index do |trace, idx|
|
67
|
-
trace_with_id = {
|
95
|
+
trace_with_id = {
|
96
|
+
exception_object_id: @exception.object_id,
|
97
|
+
id: idx,
|
98
|
+
trace: trace
|
99
|
+
}
|
68
100
|
|
69
101
|
if application_trace.include?(trace)
|
70
102
|
application_trace_with_ids << trace_with_id
|
@@ -86,6 +118,10 @@ module ActionDispatch
|
|
86
118
|
Rack::Utils.status_code(@@rescue_responses[class_name])
|
87
119
|
end
|
88
120
|
|
121
|
+
def rescue_response?
|
122
|
+
@@rescue_responses.key?(exception.class.name)
|
123
|
+
end
|
124
|
+
|
89
125
|
def source_extracts
|
90
126
|
backtrace.map do |trace|
|
91
127
|
file, line_number = extract_file_and_line_number(trace)
|
@@ -97,18 +133,31 @@ module ActionDispatch
|
|
97
133
|
end
|
98
134
|
end
|
99
135
|
|
100
|
-
|
136
|
+
def trace_to_show
|
137
|
+
if traces["Application Trace"].empty? && rescue_template != "routing_error"
|
138
|
+
"Full Trace"
|
139
|
+
else
|
140
|
+
"Application Trace"
|
141
|
+
end
|
142
|
+
end
|
101
143
|
|
144
|
+
def source_to_show_id
|
145
|
+
(traces[trace_to_show].first || {})[:id]
|
146
|
+
end
|
147
|
+
|
148
|
+
private
|
102
149
|
def backtrace
|
103
150
|
Array(@exception.backtrace)
|
104
151
|
end
|
105
152
|
|
106
|
-
def
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
153
|
+
def causes_for(exception)
|
154
|
+
return enum_for(__method__, exception) unless block_given?
|
155
|
+
|
156
|
+
yield exception while exception = exception.cause
|
157
|
+
end
|
158
|
+
|
159
|
+
def wrapped_causes_for(exception, backtrace_cleaner)
|
160
|
+
causes_for(exception).map { |cause| self.class.new(backtrace_cleaner, cause) }
|
112
161
|
end
|
113
162
|
|
114
163
|
def clean_backtrace(*args)
|
@@ -9,10 +9,13 @@ module ActionDispatch
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def call(env)
|
12
|
-
state = @executor.run!
|
12
|
+
state = @executor.run!(reset: true)
|
13
13
|
begin
|
14
14
|
response = @app.call(env)
|
15
15
|
returned = response << ::Rack::BodyProxy.new(response.pop) { state.complete! }
|
16
|
+
rescue => error
|
17
|
+
@executor.error_reporter.report(error, handled: false)
|
18
|
+
raise
|
16
19
|
ensure
|
17
20
|
state.complete! unless returned
|
18
21
|
end
|
@@ -38,7 +38,7 @@ module ActionDispatch
|
|
38
38
|
#
|
39
39
|
# See docs on the FlashHash class for more details about the flash.
|
40
40
|
class Flash
|
41
|
-
KEY = "action_dispatch.request.flash_hash"
|
41
|
+
KEY = "action_dispatch.request.flash_hash"
|
42
42
|
|
43
43
|
module RequestMethods
|
44
44
|
# Access the contents of the flash. Use <tt>flash["notice"]</tt> to
|
@@ -59,16 +59,14 @@ module ActionDispatch
|
|
59
59
|
end
|
60
60
|
|
61
61
|
def commit_flash # :nodoc:
|
62
|
-
session
|
63
|
-
flash_hash = self.flash_hash
|
62
|
+
return unless session.enabled?
|
64
63
|
|
65
64
|
if flash_hash && (flash_hash.present? || session.key?("flash"))
|
66
65
|
session["flash"] = flash_hash.to_session_value
|
67
66
|
self.flash = flash_hash.dup
|
68
67
|
end
|
69
68
|
|
70
|
-
if
|
71
|
-
session.key?("flash") && session["flash"].nil?
|
69
|
+
if session.loaded? && session.key?("flash") && session["flash"].nil?
|
72
70
|
session.delete("flash")
|
73
71
|
end
|
74
72
|
end
|
@@ -79,7 +77,7 @@ module ActionDispatch
|
|
79
77
|
end
|
80
78
|
end
|
81
79
|
|
82
|
-
class FlashNow
|
80
|
+
class FlashNow # :nodoc:
|
83
81
|
attr_accessor :flash
|
84
82
|
|
85
83
|
def initialize(flash)
|
@@ -111,7 +109,7 @@ module ActionDispatch
|
|
111
109
|
class FlashHash
|
112
110
|
include Enumerable
|
113
111
|
|
114
|
-
def self.from_session_value(value)
|
112
|
+
def self.from_session_value(value) # :nodoc:
|
115
113
|
case value
|
116
114
|
when FlashHash # Rails 3.1, 3.2
|
117
115
|
flashes = value.instance_variable_get(:@flashes)
|
@@ -132,13 +130,13 @@ module ActionDispatch
|
|
132
130
|
|
133
131
|
# Builds a hash containing the flashes to keep for the next request.
|
134
132
|
# If there are none to keep, returns +nil+.
|
135
|
-
def to_session_value
|
133
|
+
def to_session_value # :nodoc:
|
136
134
|
flashes_to_keep = @flashes.except(*@discard)
|
137
135
|
return nil if flashes_to_keep.empty?
|
138
136
|
{ "discard" => [], "flashes" => flashes_to_keep }
|
139
137
|
end
|
140
138
|
|
141
|
-
def initialize(flashes = {}, discard = [])
|
139
|
+
def initialize(flashes = {}, discard = []) # :nodoc:
|
142
140
|
@discard = Set.new(stringify_array(discard))
|
143
141
|
@flashes = flashes.stringify_keys
|
144
142
|
@now = nil
|
@@ -162,7 +160,7 @@ module ActionDispatch
|
|
162
160
|
@flashes[k.to_s]
|
163
161
|
end
|
164
162
|
|
165
|
-
def update(h)
|
163
|
+
def update(h) # :nodoc:
|
166
164
|
@discard.subtract stringify_array(h.keys)
|
167
165
|
@flashes.update h.stringify_keys
|
168
166
|
self
|
@@ -202,7 +200,7 @@ module ActionDispatch
|
|
202
200
|
|
203
201
|
alias :merge! :update
|
204
202
|
|
205
|
-
def replace(h)
|
203
|
+
def replace(h) # :nodoc:
|
206
204
|
@discard.clear
|
207
205
|
@flashes.replace h.stringify_keys
|
208
206
|
self
|
@@ -253,7 +251,7 @@ module ActionDispatch
|
|
253
251
|
# Mark for removal entries that were kept, and delete unkept ones.
|
254
252
|
#
|
255
253
|
# This method is called automatically by filters, so you generally don't need to care about it.
|
256
|
-
def sweep
|
254
|
+
def sweep # :nodoc:
|
257
255
|
@discard.each { |k| @flashes.delete k }
|
258
256
|
@discard.replace @flashes.keys
|
259
257
|
end
|