actionpack 4.1.7 → 4.2.11
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 +404 -451
- data/README.rdoc +7 -2
- data/lib/abstract_controller/base.rb +16 -6
- data/lib/abstract_controller/callbacks.rb +28 -51
- data/lib/abstract_controller/helpers.rb +11 -4
- data/lib/abstract_controller/railties/routes_helpers.rb +3 -3
- data/lib/abstract_controller/rendering.rb +7 -1
- data/lib/abstract_controller/url_for.rb +1 -1
- data/lib/action_controller/base.rb +3 -2
- data/lib/action_controller/caching/fragments.rb +7 -1
- data/lib/action_controller/caching.rb +1 -1
- data/lib/action_controller/log_subscriber.rb +26 -26
- data/lib/action_controller/metal/conditional_get.rb +37 -12
- data/lib/action_controller/metal/etag_with_template_digest.rb +50 -0
- data/lib/action_controller/metal/exceptions.rb +1 -1
- data/lib/action_controller/metal/force_ssl.rb +1 -1
- data/lib/action_controller/metal/head.rb +7 -3
- data/lib/action_controller/metal/http_authentication.rb +20 -10
- data/lib/action_controller/metal/instrumentation.rb +8 -5
- data/lib/action_controller/metal/live.rb +57 -6
- data/lib/action_controller/metal/mime_responds.rb +25 -246
- data/lib/action_controller/metal/params_wrapper.rb +5 -5
- data/lib/action_controller/metal/rack_delegation.rb +1 -1
- data/lib/action_controller/metal/redirecting.rb +14 -8
- data/lib/action_controller/metal/renderers.rb +29 -11
- data/lib/action_controller/metal/rendering.rb +2 -6
- data/lib/action_controller/metal/request_forgery_protection.rb +78 -7
- data/lib/action_controller/metal/streaming.rb +1 -1
- data/lib/action_controller/metal/strong_parameters.rb +129 -14
- data/lib/action_controller/metal/url_for.rb +11 -12
- data/lib/action_controller/metal.rb +12 -11
- data/lib/action_controller/model_naming.rb +1 -1
- data/lib/action_controller/railtie.rb +4 -0
- data/lib/action_controller/test_case.rb +119 -75
- data/lib/action_controller.rb +1 -1
- data/lib/action_dispatch/http/cache.rb +5 -4
- data/lib/action_dispatch/http/filter_parameters.rb +2 -2
- data/lib/action_dispatch/http/headers.rb +43 -9
- data/lib/action_dispatch/http/mime_negotiation.rb +10 -3
- data/lib/action_dispatch/http/mime_type.rb +18 -4
- data/lib/action_dispatch/http/parameter_filter.rb +1 -1
- data/lib/action_dispatch/http/parameters.rb +11 -26
- data/lib/action_dispatch/http/request.rb +37 -11
- data/lib/action_dispatch/http/response.rb +74 -23
- data/lib/action_dispatch/http/upload.rb +9 -8
- data/lib/action_dispatch/http/url.rb +89 -70
- data/lib/action_dispatch/journey/formatter.rb +34 -18
- data/lib/action_dispatch/journey/gtg/builder.rb +3 -3
- data/lib/action_dispatch/journey/gtg/simulator.rb +10 -7
- data/lib/action_dispatch/journey/gtg/transition_table.rb +20 -28
- data/lib/action_dispatch/journey/nfa/dot.rb +2 -2
- data/lib/action_dispatch/journey/nfa/simulator.rb +1 -1
- data/lib/action_dispatch/journey/nfa/transition_table.rb +5 -5
- data/lib/action_dispatch/journey/nodes/node.rb +4 -0
- data/lib/action_dispatch/journey/parser.rb +52 -60
- data/lib/action_dispatch/journey/parser.y +11 -10
- data/lib/action_dispatch/journey/path/pattern.rb +16 -19
- data/lib/action_dispatch/journey/route.rb +4 -19
- data/lib/action_dispatch/journey/router/strexp.rb +9 -6
- data/lib/action_dispatch/journey/router/utils.rb +1 -1
- data/lib/action_dispatch/journey/router.rb +53 -77
- data/lib/action_dispatch/journey/routes.rb +4 -0
- data/lib/action_dispatch/journey/scanner.rb +5 -5
- data/lib/action_dispatch/journey/visitors.rb +81 -92
- data/lib/action_dispatch/journey/visualizer/fsm.css +0 -4
- data/lib/action_dispatch/journey/visualizer/index.html.erb +2 -2
- data/lib/action_dispatch/middleware/callbacks.rb +1 -1
- data/lib/action_dispatch/middleware/cookies.rb +34 -34
- data/lib/action_dispatch/middleware/debug_exceptions.rb +15 -4
- data/lib/action_dispatch/middleware/exception_wrapper.rb +50 -18
- data/lib/action_dispatch/middleware/flash.rb +13 -7
- data/lib/action_dispatch/middleware/params_parser.rb +1 -1
- data/lib/action_dispatch/middleware/public_exceptions.rb +12 -3
- data/lib/action_dispatch/middleware/remote_ip.rb +40 -54
- data/lib/action_dispatch/middleware/request_id.rb +1 -1
- data/lib/action_dispatch/middleware/session/cookie_store.rb +1 -1
- data/lib/action_dispatch/middleware/show_exceptions.rb +1 -0
- data/lib/action_dispatch/middleware/ssl.rb +1 -1
- data/lib/action_dispatch/middleware/static.rb +75 -39
- data/lib/action_dispatch/middleware/templates/rescues/_source.erb +21 -19
- data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +37 -9
- data/lib/action_dispatch/middleware/templates/rescues/_trace.text.erb +2 -8
- data/lib/action_dispatch/middleware/templates/rescues/{diagnostics.erb → diagnostics.html.erb} +0 -0
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +9 -0
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +6 -0
- data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +4 -0
- data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +2 -0
- data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +1 -24
- data/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb +0 -1
- data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +120 -64
- data/lib/action_dispatch/railtie.rb +2 -0
- data/lib/action_dispatch/routing/endpoint.rb +10 -0
- data/lib/action_dispatch/routing/inspector.rb +5 -12
- data/lib/action_dispatch/routing/mapper.rb +414 -283
- data/lib/action_dispatch/routing/polymorphic_routes.rb +191 -79
- data/lib/action_dispatch/routing/redirection.rb +10 -12
- data/lib/action_dispatch/routing/route_set.rb +300 -173
- data/lib/action_dispatch/routing/routes_proxy.rb +5 -4
- data/lib/action_dispatch/routing/url_for.rb +17 -5
- data/lib/action_dispatch/testing/assertions/dom.rb +2 -26
- data/lib/action_dispatch/testing/assertions/response.rb +2 -7
- data/lib/action_dispatch/testing/assertions/routing.rb +22 -22
- data/lib/action_dispatch/testing/assertions/selector.rb +2 -429
- data/lib/action_dispatch/testing/assertions/tag.rb +2 -134
- data/lib/action_dispatch/testing/assertions.rb +11 -7
- data/lib/action_dispatch/testing/integration.rb +28 -20
- data/lib/action_dispatch/testing/test_request.rb +1 -1
- data/lib/action_dispatch/testing/test_response.rb +1 -5
- data/lib/action_pack/gem_version.rb +3 -3
- metadata +55 -13
- data/lib/action_controller/metal/responder.rb +0 -297
@@ -2,13 +2,13 @@
|
|
2
2
|
<html>
|
3
3
|
<head>
|
4
4
|
<title><%= title %></title>
|
5
|
-
<link rel="stylesheet" href="https://
|
5
|
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.css" type="text/css">
|
6
6
|
<style>
|
7
7
|
<% stylesheets.each do |style| %>
|
8
8
|
<%= style %>
|
9
9
|
<% end %>
|
10
10
|
</style>
|
11
|
-
<script src="https://
|
11
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.8/d3.min.js" type="text/javascript"></script>
|
12
12
|
</head>
|
13
13
|
<body>
|
14
14
|
<div id="wrapper">
|
@@ -3,6 +3,7 @@ require 'active_support/core_ext/module/attribute_accessors'
|
|
3
3
|
require 'active_support/core_ext/object/blank'
|
4
4
|
require 'active_support/key_generator'
|
5
5
|
require 'active_support/message_verifier'
|
6
|
+
require 'active_support/json'
|
6
7
|
|
7
8
|
module ActionDispatch
|
8
9
|
class Request < Rack::Request
|
@@ -70,11 +71,13 @@ module ActionDispatch
|
|
70
71
|
# restrict to the domain level. If you use a schema like www.example.com
|
71
72
|
# and want to share session with user.example.com set <tt>:domain</tt>
|
72
73
|
# to <tt>:all</tt>. Make sure to specify the <tt>:domain</tt> option with
|
73
|
-
# <tt>:all</tt> again when deleting cookies.
|
74
|
+
# <tt>:all</tt> or <tt>Array</tt> again when deleting cookies.
|
74
75
|
#
|
75
76
|
# domain: nil # Does not sets cookie domain. (default)
|
76
77
|
# domain: :all # Allow the cookie for the top most level
|
77
|
-
#
|
78
|
+
# # domain and subdomains.
|
79
|
+
# domain: %w(.example.com .example.org) # Allow the cookie
|
80
|
+
# # for concrete domain names.
|
78
81
|
#
|
79
82
|
# * <tt>:expires</tt> - The time at which this cookie expires, as a \Time object.
|
80
83
|
# * <tt>:secure</tt> - Whether this cookie is only transmitted to HTTPS servers.
|
@@ -90,6 +93,7 @@ module ActionDispatch
|
|
90
93
|
SECRET_TOKEN = "action_dispatch.secret_token".freeze
|
91
94
|
SECRET_KEY_BASE = "action_dispatch.secret_key_base".freeze
|
92
95
|
COOKIES_SERIALIZER = "action_dispatch.cookies_serializer".freeze
|
96
|
+
COOKIES_DIGEST = "action_dispatch.cookies_digest".freeze
|
93
97
|
|
94
98
|
# Cookies can typically store 4096 bytes.
|
95
99
|
MAX_COOKIE_SIZE = 4096
|
@@ -118,7 +122,7 @@ module ActionDispatch
|
|
118
122
|
# the cookie again. This is useful for creating cookies with values that the user is not supposed to change. If a signed
|
119
123
|
# cookie was tampered with by the user (or a 3rd party), nil will be returned.
|
120
124
|
#
|
121
|
-
# If +secrets.secret_key_base+ and +
|
125
|
+
# If +secrets.secret_key_base+ and +secrets.secret_token+ (deprecated) are both set,
|
122
126
|
# legacy cookies signed with the old key generator will be transparently upgraded.
|
123
127
|
#
|
124
128
|
# This jar requires that you set a suitable secret for the verification on your app's +secrets.secret_key_base+.
|
@@ -141,7 +145,7 @@ module ActionDispatch
|
|
141
145
|
# Returns a jar that'll automatically encrypt cookie values before sending them to the client and will decrypt them for read.
|
142
146
|
# If the cookie was tampered with by the user (or a 3rd party), nil will be returned.
|
143
147
|
#
|
144
|
-
# If +secrets.secret_key_base+ and +
|
148
|
+
# If +secrets.secret_key_base+ and +secrets.secret_token+ (deprecated) are both set,
|
145
149
|
# legacy cookies signed with the old key generator will be transparently upgraded.
|
146
150
|
#
|
147
151
|
# This jar requires that you set a suitable secret for the verification on your app's +secrets.secret_key_base+.
|
@@ -173,10 +177,14 @@ module ActionDispatch
|
|
173
177
|
end
|
174
178
|
end
|
175
179
|
|
176
|
-
|
180
|
+
# Passing the ActiveSupport::MessageEncryptor::NullSerializer downstream
|
181
|
+
# to the Message{Encryptor,Verifier} allows us to handle the
|
182
|
+
# (de)serialization step within the cookie jar, which gives us the
|
183
|
+
# opportunity to detect and migrate legacy cookies.
|
184
|
+
module VerifyAndUpgradeLegacySignedMessage # :nodoc:
|
177
185
|
def initialize(*args)
|
178
186
|
super
|
179
|
-
@legacy_verifier = ActiveSupport::MessageVerifier.new(@options[:secret_token], serializer: NullSerializer)
|
187
|
+
@legacy_verifier = ActiveSupport::MessageVerifier.new(@options[:secret_token], serializer: ActiveSupport::MessageEncryptor::NullSerializer)
|
180
188
|
end
|
181
189
|
|
182
190
|
def verify_and_upgrade_legacy_signed_message(name, signed_message)
|
@@ -212,7 +220,8 @@ module ActionDispatch
|
|
212
220
|
secret_token: env[SECRET_TOKEN],
|
213
221
|
secret_key_base: env[SECRET_KEY_BASE],
|
214
222
|
upgrade_legacy_signed_cookies: env[SECRET_TOKEN].present? && env[SECRET_KEY_BASE].present?,
|
215
|
-
serializer: env[COOKIES_SERIALIZER]
|
223
|
+
serializer: env[COOKIES_SERIALIZER],
|
224
|
+
digest: env[COOKIES_DIGEST]
|
216
225
|
}
|
217
226
|
end
|
218
227
|
|
@@ -289,8 +298,8 @@ module ActionDispatch
|
|
289
298
|
end
|
290
299
|
end
|
291
300
|
|
292
|
-
# Sets the cookie named +name+. The second argument may be the
|
293
|
-
# value
|
301
|
+
# Sets the cookie named +name+. The second argument may be the cookie's
|
302
|
+
# value or a hash of options as documented above.
|
294
303
|
def []=(name, options)
|
295
304
|
if options.is_a?(Hash)
|
296
305
|
options.symbolize_keys!
|
@@ -302,7 +311,7 @@ module ActionDispatch
|
|
302
311
|
|
303
312
|
handle_options(options)
|
304
313
|
|
305
|
-
if @cookies[name.to_s] != value
|
314
|
+
if @cookies[name.to_s] != value || options[:expires]
|
306
315
|
@cookies[name.to_s] = value
|
307
316
|
@set_cookies[name.to_s] = options
|
308
317
|
@delete_cookies.delete(name.to_s)
|
@@ -383,30 +392,17 @@ module ActionDispatch
|
|
383
392
|
end
|
384
393
|
end
|
385
394
|
|
386
|
-
class JsonSerializer
|
395
|
+
class JsonSerializer # :nodoc:
|
387
396
|
def self.load(value)
|
388
|
-
JSON.
|
397
|
+
ActiveSupport::JSON.decode(value)
|
389
398
|
end
|
390
399
|
|
391
400
|
def self.dump(value)
|
392
|
-
JSON.
|
401
|
+
ActiveSupport::JSON.encode(value)
|
393
402
|
end
|
394
403
|
end
|
395
404
|
|
396
|
-
|
397
|
-
# allows us to handle the (de)serialization step within the cookie jar,
|
398
|
-
# which gives us the opportunity to detect and migrate legacy cookies.
|
399
|
-
class NullSerializer
|
400
|
-
def self.load(value)
|
401
|
-
value
|
402
|
-
end
|
403
|
-
|
404
|
-
def self.dump(value)
|
405
|
-
value
|
406
|
-
end
|
407
|
-
end
|
408
|
-
|
409
|
-
module SerializedCookieJars
|
405
|
+
module SerializedCookieJars # :nodoc:
|
410
406
|
MARSHAL_SIGNATURE = "\x04\x08".freeze
|
411
407
|
|
412
408
|
protected
|
@@ -441,6 +437,10 @@ module ActionDispatch
|
|
441
437
|
serializer
|
442
438
|
end
|
443
439
|
end
|
440
|
+
|
441
|
+
def digest
|
442
|
+
@options[:digest] || 'SHA1'
|
443
|
+
end
|
444
444
|
end
|
445
445
|
|
446
446
|
class SignedCookieJar #:nodoc:
|
@@ -451,7 +451,7 @@ module ActionDispatch
|
|
451
451
|
@parent_jar = parent_jar
|
452
452
|
@options = options
|
453
453
|
secret = key_generator.generate_key(@options[:signed_cookie_salt])
|
454
|
-
@verifier = ActiveSupport::MessageVerifier.new(secret, serializer: NullSerializer)
|
454
|
+
@verifier = ActiveSupport::MessageVerifier.new(secret, digest: digest, serializer: ActiveSupport::MessageEncryptor::NullSerializer)
|
455
455
|
end
|
456
456
|
|
457
457
|
def [](name)
|
@@ -468,7 +468,7 @@ module ActionDispatch
|
|
468
468
|
options = { :value => @verifier.generate(serialize(name, options)) }
|
469
469
|
end
|
470
470
|
|
471
|
-
raise CookieOverflow if options[:value].
|
471
|
+
raise CookieOverflow if options[:value].bytesize > MAX_COOKIE_SIZE
|
472
472
|
@parent_jar[name] = options
|
473
473
|
end
|
474
474
|
|
@@ -481,7 +481,7 @@ module ActionDispatch
|
|
481
481
|
end
|
482
482
|
|
483
483
|
# UpgradeLegacySignedCookieJar is used instead of SignedCookieJar if
|
484
|
-
#
|
484
|
+
# secrets.secret_token and secrets.secret_key_base are both set. It reads
|
485
485
|
# legacy cookies signed with the old dummy key generator and re-saves
|
486
486
|
# them using the new key generator to provide a smooth upgrade path.
|
487
487
|
class UpgradeLegacySignedCookieJar < SignedCookieJar #:nodoc:
|
@@ -506,9 +506,9 @@ module ActionDispatch
|
|
506
506
|
|
507
507
|
@parent_jar = parent_jar
|
508
508
|
@options = options
|
509
|
-
secret = key_generator.generate_key(@options[:encrypted_cookie_salt])
|
509
|
+
secret = key_generator.generate_key(@options[:encrypted_cookie_salt])[0, ActiveSupport::MessageEncryptor.key_len]
|
510
510
|
sign_secret = key_generator.generate_key(@options[:encrypted_signed_cookie_salt])
|
511
|
-
@encryptor = ActiveSupport::MessageEncryptor.new(secret, sign_secret, serializer: NullSerializer)
|
511
|
+
@encryptor = ActiveSupport::MessageEncryptor.new(secret, sign_secret, digest: digest, serializer: ActiveSupport::MessageEncryptor::NullSerializer)
|
512
512
|
end
|
513
513
|
|
514
514
|
def [](name)
|
@@ -526,7 +526,7 @@ module ActionDispatch
|
|
526
526
|
|
527
527
|
options[:value] = @encryptor.encrypt_and_sign(serialize(name, options[:value]))
|
528
528
|
|
529
|
-
raise CookieOverflow if options[:value].
|
529
|
+
raise CookieOverflow if options[:value].bytesize > MAX_COOKIE_SIZE
|
530
530
|
@parent_jar[name] = options
|
531
531
|
end
|
532
532
|
|
@@ -539,7 +539,7 @@ module ActionDispatch
|
|
539
539
|
end
|
540
540
|
|
541
541
|
# UpgradeLegacyEncryptedCookieJar is used by ActionDispatch::Session::CookieStore
|
542
|
-
# instead of EncryptedCookieJar if
|
542
|
+
# instead of EncryptedCookieJar if secrets.secret_token and secrets.secret_key_base
|
543
543
|
# are both set. It reads legacy cookies signed with the old dummy key generator and
|
544
544
|
# encrypts and re-saves them using the new key generator to provide a smooth upgrade path.
|
545
545
|
class UpgradeLegacyEncryptedCookieJar < EncryptedCookieJar #:nodoc:
|
@@ -35,14 +35,25 @@ module ActionDispatch
|
|
35
35
|
|
36
36
|
if env['action_dispatch.show_detailed_exceptions']
|
37
37
|
request = Request.new(env)
|
38
|
+
traces = wrapper.traces
|
39
|
+
|
40
|
+
trace_to_show = 'Application Trace'
|
41
|
+
if traces[trace_to_show].empty? && wrapper.rescue_template != 'routing_error'
|
42
|
+
trace_to_show = 'Full Trace'
|
43
|
+
end
|
44
|
+
|
45
|
+
if source_to_show = traces[trace_to_show].first
|
46
|
+
source_to_show_id = source_to_show[:id]
|
47
|
+
end
|
48
|
+
|
38
49
|
template = ActionView::Base.new([RESCUES_TEMPLATE_PATH],
|
39
50
|
request: request,
|
40
51
|
exception: wrapper.exception,
|
41
|
-
|
42
|
-
|
43
|
-
|
52
|
+
traces: traces,
|
53
|
+
show_source_idx: source_to_show_id,
|
54
|
+
trace_to_show: trace_to_show,
|
44
55
|
routes_inspector: routes_inspector(exception),
|
45
|
-
|
56
|
+
source_extracts: wrapper.source_extracts,
|
46
57
|
line_number: wrapper.line_number,
|
47
58
|
file: wrapper.file
|
48
59
|
)
|
@@ -6,16 +6,17 @@ module ActionDispatch
|
|
6
6
|
cattr_accessor :rescue_responses
|
7
7
|
@@rescue_responses = Hash.new(:internal_server_error)
|
8
8
|
@@rescue_responses.merge!(
|
9
|
-
'ActionController::RoutingError'
|
10
|
-
'AbstractController::ActionNotFound'
|
11
|
-
'ActionController::MethodNotAllowed'
|
12
|
-
'ActionController::UnknownHttpMethod'
|
13
|
-
'ActionController::NotImplemented'
|
14
|
-
'ActionController::UnknownFormat'
|
15
|
-
'ActionController::InvalidAuthenticityToken'
|
16
|
-
'
|
17
|
-
'
|
18
|
-
'ActionController::
|
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
|
+
'ActionController::InvalidAuthenticityToken' => :unprocessable_entity,
|
16
|
+
'ActionController::InvalidCrossOriginRequest' => :unprocessable_entity,
|
17
|
+
'ActionDispatch::ParamsParser::ParseError' => :bad_request,
|
18
|
+
'ActionController::BadRequest' => :bad_request,
|
19
|
+
'ActionController::ParameterMissing' => :bad_request
|
19
20
|
)
|
20
21
|
|
21
22
|
cattr_accessor :rescue_templates
|
@@ -56,21 +57,52 @@ module ActionDispatch
|
|
56
57
|
clean_backtrace(:all)
|
57
58
|
end
|
58
59
|
|
60
|
+
def traces
|
61
|
+
appplication_trace_with_ids = []
|
62
|
+
framework_trace_with_ids = []
|
63
|
+
full_trace_with_ids = []
|
64
|
+
|
65
|
+
full_trace.each_with_index do |trace, idx|
|
66
|
+
trace_with_id = { id: idx, trace: trace }
|
67
|
+
|
68
|
+
if application_trace.include?(trace)
|
69
|
+
appplication_trace_with_ids << trace_with_id
|
70
|
+
else
|
71
|
+
framework_trace_with_ids << trace_with_id
|
72
|
+
end
|
73
|
+
|
74
|
+
full_trace_with_ids << trace_with_id
|
75
|
+
end
|
76
|
+
|
77
|
+
{
|
78
|
+
"Application Trace" => appplication_trace_with_ids,
|
79
|
+
"Framework Trace" => framework_trace_with_ids,
|
80
|
+
"Full Trace" => full_trace_with_ids
|
81
|
+
}
|
82
|
+
end
|
83
|
+
|
59
84
|
def self.status_code_for_exception(class_name)
|
60
85
|
Rack::Utils.status_code(@@rescue_responses[class_name])
|
61
86
|
end
|
62
87
|
|
63
|
-
def
|
64
|
-
|
65
|
-
file, line
|
66
|
-
|
67
|
-
|
68
|
-
|
88
|
+
def source_extracts
|
89
|
+
backtrace.map do |trace|
|
90
|
+
file, line = trace.split(":")
|
91
|
+
line_number = line.to_i
|
92
|
+
|
93
|
+
{
|
94
|
+
code: source_fragment(file, line_number),
|
95
|
+
line_number: line_number
|
96
|
+
}
|
69
97
|
end
|
70
98
|
end
|
71
99
|
|
72
100
|
private
|
73
101
|
|
102
|
+
def backtrace
|
103
|
+
Array(@exception.backtrace)
|
104
|
+
end
|
105
|
+
|
74
106
|
def original_exception(exception)
|
75
107
|
if registered_original_exception?(exception)
|
76
108
|
exception.original_exception
|
@@ -85,9 +117,9 @@ module ActionDispatch
|
|
85
117
|
|
86
118
|
def clean_backtrace(*args)
|
87
119
|
if backtrace_cleaner
|
88
|
-
backtrace_cleaner.clean(
|
120
|
+
backtrace_cleaner.clean(backtrace, *args)
|
89
121
|
else
|
90
|
-
|
122
|
+
backtrace
|
91
123
|
end
|
92
124
|
end
|
93
125
|
|
@@ -10,7 +10,7 @@ module ActionDispatch
|
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
13
|
-
# The flash provides a way to pass temporary
|
13
|
+
# The flash provides a way to pass temporary primitive-types (String, Array, Hash) between actions. Anything you place in the flash will be exposed
|
14
14
|
# to the very next action and then cleared out. This is a great way of doing notices and alerts, such as a create
|
15
15
|
# action that sets <tt>flash[:notice] = "Post successfully created"</tt> before redirecting to a display action that can
|
16
16
|
# then expose the flash to its template. Actually, that exposure is automatically done.
|
@@ -37,8 +37,11 @@ module ActionDispatch
|
|
37
37
|
# flash.alert = "You must be logged in"
|
38
38
|
# flash.notice = "Post successfully created"
|
39
39
|
#
|
40
|
-
# This example
|
41
|
-
#
|
40
|
+
# This example places a string in the flash. And of course, you can put as many as you like at a time too. If you want to pass
|
41
|
+
# non-primitive types, you will have to handle that in your application. Example: To show messages with links, you will have to
|
42
|
+
# use sanitize helper.
|
43
|
+
#
|
44
|
+
# Just remember: They'll be gone by the time the next action has been performed.
|
42
45
|
#
|
43
46
|
# See docs on the FlashHash class for more details about the flash.
|
44
47
|
class Flash
|
@@ -76,7 +79,7 @@ module ActionDispatch
|
|
76
79
|
class FlashHash
|
77
80
|
include Enumerable
|
78
81
|
|
79
|
-
def self.from_session_value(value)
|
82
|
+
def self.from_session_value(value) #:nodoc:
|
80
83
|
flash = case value
|
81
84
|
when FlashHash # Rails 3.1, 3.2
|
82
85
|
new(value.instance_variable_get(:@flashes), value.instance_variable_get(:@used))
|
@@ -88,8 +91,11 @@ module ActionDispatch
|
|
88
91
|
|
89
92
|
flash.tap(&:sweep)
|
90
93
|
end
|
91
|
-
|
92
|
-
|
94
|
+
|
95
|
+
# Builds a hash containing the discarded values and the hashes
|
96
|
+
# representing the flashes.
|
97
|
+
# If there are no values in @flashes, returns nil.
|
98
|
+
def to_session_value #:nodoc:
|
93
99
|
return nil if empty?
|
94
100
|
{'discard' => @discard.to_a, 'flashes' => @flashes}
|
95
101
|
end
|
@@ -129,7 +135,7 @@ module ActionDispatch
|
|
129
135
|
end
|
130
136
|
|
131
137
|
def key?(name)
|
132
|
-
@flashes.key? name
|
138
|
+
@flashes.key? name.to_s
|
133
139
|
end
|
134
140
|
|
135
141
|
def delete(key)
|
@@ -47,7 +47,7 @@ module ActionDispatch
|
|
47
47
|
else
|
48
48
|
false
|
49
49
|
end
|
50
|
-
rescue
|
50
|
+
rescue => e # JSON or Ruby code block errors
|
51
51
|
logger(env).debug "Error occurred while parsing request parameters.\nContents:\n\n#{request.raw_post}"
|
52
52
|
|
53
53
|
raise ParseError.new(e.message, e)
|
@@ -1,4 +1,14 @@
|
|
1
1
|
module ActionDispatch
|
2
|
+
# When called, this middleware renders an error page. By default if an HTML
|
3
|
+
# response is expected it will render static error pages from the `/public`
|
4
|
+
# directory. For example when this middleware receives a 500 response it will
|
5
|
+
# render the template found in `/public/500.html`.
|
6
|
+
# If an internationalized locale is set, this middleware will attempt to render
|
7
|
+
# the template in `/public/500.<locale>.html`. If an internationalized template
|
8
|
+
# is not found it will fall back on `/public/500.html`.
|
9
|
+
#
|
10
|
+
# When a request with a content type other than HTML is made, this middleware
|
11
|
+
# will attempt to convert error information into the appropriate response type.
|
2
12
|
class PublicExceptions
|
3
13
|
attr_accessor :public_path
|
4
14
|
|
@@ -32,9 +42,8 @@ module ActionDispatch
|
|
32
42
|
end
|
33
43
|
|
34
44
|
def render_html(status)
|
35
|
-
|
36
|
-
path = "#{public_path}/#{status}
|
37
|
-
path = "#{public_path}/#{status}.html" unless path && (found = File.exist?(path))
|
45
|
+
path = "#{public_path}/#{status}.#{I18n.locale}.html"
|
46
|
+
path = "#{public_path}/#{status}.html" unless (found = File.exist?(path))
|
38
47
|
|
39
48
|
if found || File.exist?(path)
|
40
49
|
render_format(status, 'text/html', File.read(path))
|