actionpack 7.0.8.1 → 7.1.3.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 +365 -353
- data/MIT-LICENSE +1 -1
- data/README.rdoc +2 -2
- data/lib/abstract_controller/base.rb +20 -11
- data/lib/abstract_controller/caching/fragments.rb +2 -0
- data/lib/abstract_controller/callbacks.rb +31 -6
- data/lib/abstract_controller/deprecator.rb +7 -0
- data/lib/abstract_controller/helpers.rb +61 -18
- data/lib/abstract_controller/railties/routes_helpers.rb +1 -16
- data/lib/abstract_controller/rendering.rb +3 -3
- data/lib/abstract_controller/translation.rb +1 -20
- data/lib/abstract_controller/url_for.rb +2 -0
- data/lib/abstract_controller.rb +6 -0
- data/lib/action_controller/api.rb +5 -3
- data/lib/action_controller/base.rb +3 -17
- data/lib/action_controller/caching.rb +2 -0
- data/lib/action_controller/deprecator.rb +7 -0
- data/lib/action_controller/form_builder.rb +2 -0
- data/lib/action_controller/log_subscriber.rb +16 -4
- data/lib/action_controller/metal/content_security_policy.rb +1 -1
- data/lib/action_controller/metal/data_streaming.rb +2 -0
- data/lib/action_controller/metal/default_headers.rb +2 -0
- data/lib/action_controller/metal/etag_with_flash.rb +2 -0
- data/lib/action_controller/metal/etag_with_template_digest.rb +2 -0
- data/lib/action_controller/metal/exceptions.rb +8 -0
- data/lib/action_controller/metal/head.rb +8 -6
- data/lib/action_controller/metal/helpers.rb +3 -14
- data/lib/action_controller/metal/http_authentication.rb +17 -8
- data/lib/action_controller/metal/implicit_render.rb +5 -3
- data/lib/action_controller/metal/instrumentation.rb +8 -1
- data/lib/action_controller/metal/live.rb +24 -0
- data/lib/action_controller/metal/mime_responds.rb +2 -2
- data/lib/action_controller/metal/params_wrapper.rb +4 -2
- data/lib/action_controller/metal/permissions_policy.rb +1 -1
- data/lib/action_controller/metal/redirecting.rb +7 -7
- data/lib/action_controller/metal/renderers.rb +2 -2
- data/lib/action_controller/metal/rendering.rb +0 -7
- data/lib/action_controller/metal/request_forgery_protection.rb +139 -50
- data/lib/action_controller/metal/rescue.rb +2 -0
- data/lib/action_controller/metal/streaming.rb +70 -30
- data/lib/action_controller/metal/strong_parameters.rb +132 -52
- data/lib/action_controller/metal/url_for.rb +7 -0
- data/lib/action_controller/metal.rb +79 -21
- data/lib/action_controller/railtie.rb +22 -9
- data/lib/action_controller/renderer.rb +98 -65
- data/lib/action_controller/test_case.rb +15 -5
- data/lib/action_controller.rb +8 -1
- data/lib/action_dispatch/constants.rb +32 -0
- data/lib/action_dispatch/deprecator.rb +7 -0
- data/lib/action_dispatch/http/cache.rb +1 -3
- data/lib/action_dispatch/http/content_security_policy.rb +9 -8
- data/lib/action_dispatch/http/filter_parameters.rb +11 -5
- data/lib/action_dispatch/http/headers.rb +2 -0
- data/lib/action_dispatch/http/mime_negotiation.rb +22 -22
- data/lib/action_dispatch/http/mime_type.rb +35 -12
- data/lib/action_dispatch/http/mime_types.rb +3 -1
- data/lib/action_dispatch/http/parameters.rb +1 -1
- data/lib/action_dispatch/http/permissions_policy.rb +38 -23
- data/lib/action_dispatch/http/rack_cache.rb +2 -0
- data/lib/action_dispatch/http/request.rb +48 -14
- data/lib/action_dispatch/http/response.rb +80 -59
- data/lib/action_dispatch/http/upload.rb +2 -0
- data/lib/action_dispatch/journey/formatter.rb +8 -2
- data/lib/action_dispatch/journey/path/pattern.rb +14 -14
- data/lib/action_dispatch/journey/route.rb +3 -2
- data/lib/action_dispatch/journey/router.rb +9 -8
- data/lib/action_dispatch/journey/routes.rb +2 -2
- data/lib/action_dispatch/log_subscriber.rb +23 -0
- data/lib/action_dispatch/middleware/actionable_exceptions.rb +5 -6
- data/lib/action_dispatch/middleware/assume_ssl.rb +24 -0
- data/lib/action_dispatch/middleware/callbacks.rb +2 -0
- data/lib/action_dispatch/middleware/cookies.rb +81 -98
- data/lib/action_dispatch/middleware/debug_exceptions.rb +26 -25
- data/lib/action_dispatch/middleware/debug_locks.rb +4 -1
- data/lib/action_dispatch/middleware/debug_view.rb +7 -2
- data/lib/action_dispatch/middleware/exception_wrapper.rb +186 -27
- data/lib/action_dispatch/middleware/executor.rb +1 -1
- data/lib/action_dispatch/middleware/flash.rb +7 -0
- data/lib/action_dispatch/middleware/host_authorization.rb +6 -3
- data/lib/action_dispatch/middleware/public_exceptions.rb +5 -3
- data/lib/action_dispatch/middleware/reloader.rb +7 -5
- data/lib/action_dispatch/middleware/remote_ip.rb +17 -16
- data/lib/action_dispatch/middleware/request_id.rb +2 -0
- data/lib/action_dispatch/middleware/server_timing.rb +4 -4
- data/lib/action_dispatch/middleware/session/abstract_store.rb +5 -0
- data/lib/action_dispatch/middleware/session/cache_store.rb +2 -0
- data/lib/action_dispatch/middleware/session/cookie_store.rb +11 -5
- data/lib/action_dispatch/middleware/session/mem_cache_store.rb +3 -1
- data/lib/action_dispatch/middleware/show_exceptions.rb +19 -15
- data/lib/action_dispatch/middleware/ssl.rb +18 -6
- data/lib/action_dispatch/middleware/stack.rb +7 -2
- data/lib/action_dispatch/middleware/static.rb +12 -8
- data/lib/action_dispatch/middleware/templates/rescues/_actions.html.erb +2 -2
- data/lib/action_dispatch/middleware/templates/rescues/_message_and_suggestions.html.erb +4 -4
- data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +8 -1
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +7 -7
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +2 -2
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +17 -0
- data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +16 -12
- data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +3 -3
- data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +4 -4
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.text.erb +1 -1
- data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +3 -0
- data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +46 -37
- data/lib/action_dispatch/railtie.rb +14 -4
- data/lib/action_dispatch/request/session.rb +16 -6
- data/lib/action_dispatch/request/utils.rb +8 -3
- data/lib/action_dispatch/routing/inspector.rb +54 -6
- data/lib/action_dispatch/routing/mapper.rb +35 -24
- data/lib/action_dispatch/routing/polymorphic_routes.rb +2 -0
- data/lib/action_dispatch/routing/redirection.rb +15 -6
- data/lib/action_dispatch/routing/route_set.rb +52 -22
- data/lib/action_dispatch/routing/routes_proxy.rb +10 -15
- data/lib/action_dispatch/routing/url_for.rb +5 -1
- data/lib/action_dispatch/routing.rb +7 -7
- data/lib/action_dispatch/system_test_case.rb +3 -3
- data/lib/action_dispatch/system_testing/browser.rb +20 -19
- data/lib/action_dispatch/system_testing/driver.rb +13 -21
- data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +27 -16
- data/lib/action_dispatch/testing/assertion_response.rb +1 -1
- data/lib/action_dispatch/testing/assertions/response.rb +13 -6
- data/lib/action_dispatch/testing/assertions/routing.rb +67 -28
- data/lib/action_dispatch/testing/assertions.rb +3 -1
- data/lib/action_dispatch/testing/integration.rb +27 -17
- data/lib/action_dispatch/testing/request_encoder.rb +4 -1
- data/lib/action_dispatch/testing/test_process.rb +4 -3
- data/lib/action_dispatch/testing/test_request.rb +1 -1
- data/lib/action_dispatch/testing/test_response.rb +23 -9
- data/lib/action_dispatch.rb +37 -4
- data/lib/action_pack/gem_version.rb +4 -4
- data/lib/action_pack/version.rb +1 -1
- data/lib/action_pack.rb +1 -1
- metadata +64 -28
@@ -4,6 +4,8 @@ require "securerandom"
|
|
4
4
|
require "active_support/core_ext/string/access"
|
5
5
|
|
6
6
|
module ActionDispatch
|
7
|
+
# = Action Dispatch \RequestId
|
8
|
+
#
|
7
9
|
# Makes a unique request id available to the +action_dispatch.request_id+ env variable (which is then accessible
|
8
10
|
# through ActionDispatch::Request#request_id or the alias ActionDispatch::Request#uuid) and sends
|
9
11
|
# the same id to the client via the +X-Request-Id+ header.
|
@@ -4,8 +4,6 @@ require "active_support/notifications"
|
|
4
4
|
|
5
5
|
module ActionDispatch
|
6
6
|
class ServerTiming
|
7
|
-
SERVER_TIMING_HEADER = "Server-Timing"
|
8
|
-
|
9
7
|
class Subscriber # :nodoc:
|
10
8
|
include Singleton
|
11
9
|
KEY = :action_dispatch_server_timing_events
|
@@ -67,8 +65,10 @@ module ActionDispatch
|
|
67
65
|
"%s;dur=%.2f" % [event_name, events_collection.sum(&:duration)]
|
68
66
|
end
|
69
67
|
|
70
|
-
|
71
|
-
|
68
|
+
if headers[ActionDispatch::Constants::SERVER_TIMING].present?
|
69
|
+
header_info.prepend(headers[ActionDispatch::Constants::SERVER_TIMING])
|
70
|
+
end
|
71
|
+
headers[ActionDispatch::Constants::SERVER_TIMING] = header_info.join(", ")
|
72
72
|
|
73
73
|
response
|
74
74
|
end
|
@@ -4,6 +4,8 @@ require "action_dispatch/middleware/session/abstract_store"
|
|
4
4
|
|
5
5
|
module ActionDispatch
|
6
6
|
module Session
|
7
|
+
# = Action Dispatch Session \CacheStore
|
8
|
+
#
|
7
9
|
# A session store that uses an ActiveSupport::Cache::Store to store the sessions. This store is most useful
|
8
10
|
# if you don't store critical data in your sessions and you don't need them to live for extended periods
|
9
11
|
# of time.
|
@@ -6,7 +6,9 @@ require "rack/session/cookie"
|
|
6
6
|
|
7
7
|
module ActionDispatch
|
8
8
|
module Session
|
9
|
-
#
|
9
|
+
# = Action Dispatch Session \CookieStore
|
10
|
+
#
|
11
|
+
# This cookie-based session store is the \Rails default. It is
|
10
12
|
# dramatically faster than the alternatives.
|
11
13
|
#
|
12
14
|
# Sessions typically contain at most a user ID and flash message; both fit
|
@@ -18,18 +20,18 @@ module ActionDispatch
|
|
18
20
|
#
|
19
21
|
# Your cookies will be encrypted using your application's +secret_key_base+. This
|
20
22
|
# goes a step further than signed cookies in that encrypted cookies cannot
|
21
|
-
# be altered or read by users. This is the default starting in Rails 4.
|
23
|
+
# be altered or read by users. This is the default starting in \Rails 4.
|
22
24
|
#
|
23
25
|
# Configure your session store in an initializer:
|
24
26
|
#
|
25
27
|
# Rails.application.config.session_store :cookie_store, key: '_your_app_session'
|
26
28
|
#
|
27
29
|
# In the development and test environments your application's +secret_key_base+ is
|
28
|
-
# generated by Rails and stored in a temporary file in <tt>tmp/
|
30
|
+
# generated by \Rails and stored in a temporary file in <tt>tmp/local_secret.txt</tt>.
|
29
31
|
# In all other environments, it is stored encrypted in the
|
30
32
|
# <tt>config/credentials.yml.enc</tt> file.
|
31
33
|
#
|
32
|
-
# If your application was not updated to Rails 5.2 defaults, the +secret_key_base+
|
34
|
+
# If your application was not updated to \Rails 5.2 defaults, the +secret_key_base+
|
33
35
|
# will be found in the old <tt>config/secrets.yml</tt> file.
|
34
36
|
#
|
35
37
|
# Note that changing your +secret_key_base+ will invalidate all existing session.
|
@@ -56,8 +58,12 @@ module ActionDispatch
|
|
56
58
|
end
|
57
59
|
end
|
58
60
|
|
61
|
+
DEFAULT_SAME_SITE = proc { |request| request.cookies_same_site_protection } # :nodoc:
|
62
|
+
|
59
63
|
def initialize(app, options = {})
|
60
|
-
|
64
|
+
options[:cookie_only] = true
|
65
|
+
options[:same_site] = DEFAULT_SAME_SITE if !options.key?(:same_site)
|
66
|
+
super
|
61
67
|
end
|
62
68
|
|
63
69
|
def delete_session(req, session_id, options)
|
@@ -4,12 +4,14 @@ require "action_dispatch/middleware/session/abstract_store"
|
|
4
4
|
begin
|
5
5
|
require "rack/session/dalli"
|
6
6
|
rescue LoadError => e
|
7
|
-
|
7
|
+
warn "You don't have dalli installed in your application. Please add it to your Gemfile and run bundle install"
|
8
8
|
raise e
|
9
9
|
end
|
10
10
|
|
11
11
|
module ActionDispatch
|
12
12
|
module Session
|
13
|
+
# = Action Dispatch Session \MemCacheStore
|
14
|
+
#
|
13
15
|
# A session store that uses MemCache to implement storage.
|
14
16
|
#
|
15
17
|
# ==== Options
|
@@ -3,21 +3,24 @@
|
|
3
3
|
require "action_dispatch/middleware/exception_wrapper"
|
4
4
|
|
5
5
|
module ActionDispatch
|
6
|
+
# = Action Dispatch \ShowExceptions
|
7
|
+
#
|
6
8
|
# This middleware rescues any exception returned by the application
|
7
9
|
# and calls an exceptions app that will wrap it in a format for the end user.
|
8
10
|
#
|
9
11
|
# The exceptions app should be passed as a parameter on initialization of
|
10
12
|
# +ShowExceptions+. Every time there is an exception, +ShowExceptions+ will
|
11
13
|
# store the exception in <tt>env["action_dispatch.exception"]</tt>, rewrite
|
12
|
-
# the +PATH_INFO+ to the exception status code and call the Rack app.
|
14
|
+
# the +PATH_INFO+ to the exception status code, and call the Rack app.
|
13
15
|
#
|
14
16
|
# In \Rails applications, the exceptions app can be configured with
|
15
17
|
# +config.exceptions_app+, which defaults to ActionDispatch::PublicExceptions.
|
16
18
|
#
|
17
|
-
# If the application returns
|
18
|
-
# middleware will send an empty response as a
|
19
|
-
# code. If any exception happens inside the
|
20
|
-
# catches the exceptions and returns a
|
19
|
+
# If the application returns a response with the <tt>X-Cascade</tt> header
|
20
|
+
# set to <tt>"pass"</tt>, this middleware will send an empty response as a
|
21
|
+
# result with the correct status code. If any exception happens inside the
|
22
|
+
# exceptions app, this middleware catches the exceptions and returns a
|
23
|
+
# failsafe response.
|
21
24
|
class ShowExceptions
|
22
25
|
def initialize(app, exceptions_app)
|
23
26
|
@app = app
|
@@ -25,21 +28,21 @@ module ActionDispatch
|
|
25
28
|
end
|
26
29
|
|
27
30
|
def call(env)
|
28
|
-
request = ActionDispatch::Request.new env
|
29
31
|
@app.call(env)
|
30
32
|
rescue Exception => exception
|
31
|
-
|
32
|
-
|
33
|
+
request = ActionDispatch::Request.new env
|
34
|
+
backtrace_cleaner = request.get_header("action_dispatch.backtrace_cleaner")
|
35
|
+
wrapper = ExceptionWrapper.new(backtrace_cleaner, exception)
|
36
|
+
if wrapper.show?(request)
|
37
|
+
render_exception(request, wrapper)
|
33
38
|
else
|
34
39
|
raise exception
|
35
40
|
end
|
36
41
|
end
|
37
42
|
|
38
43
|
private
|
39
|
-
def render_exception(request,
|
40
|
-
|
41
|
-
wrapper = ExceptionWrapper.new(backtrace_cleaner, exception)
|
42
|
-
status = wrapper.status_code
|
44
|
+
def render_exception(request, wrapper)
|
45
|
+
status = wrapper.status_code
|
43
46
|
request.set_header "action_dispatch.exception", wrapper.unwrapped_exception
|
44
47
|
request.set_header "action_dispatch.original_path", request.path_info
|
45
48
|
request.set_header "action_dispatch.original_request_method", request.raw_request_method
|
@@ -47,11 +50,11 @@ module ActionDispatch
|
|
47
50
|
request.path_info = "/#{status}"
|
48
51
|
request.request_method = "GET"
|
49
52
|
response = @exceptions_app.call(request.env)
|
50
|
-
response[1][
|
53
|
+
response[1][Constants::X_CASCADE] == "pass" ? pass_response(status) : response
|
51
54
|
rescue Exception => failsafe_error
|
52
55
|
$stderr.puts "Error during failsafe response: #{failsafe_error}\n #{failsafe_error.backtrace * "\n "}"
|
53
56
|
|
54
|
-
[500, {
|
57
|
+
[500, { Rack::CONTENT_TYPE => "text/plain; charset=utf-8" },
|
55
58
|
["500 Internal Server Error\n" \
|
56
59
|
"If you are the administrator of this website, then please read this web " \
|
57
60
|
"application's log file and/or the web server's log file to find out what " \
|
@@ -68,7 +71,8 @@ module ActionDispatch
|
|
68
71
|
end
|
69
72
|
|
70
73
|
def pass_response(status)
|
71
|
-
[status, {
|
74
|
+
[status, { Rack::CONTENT_TYPE => "text/html; charset=#{Response.default_charset}",
|
75
|
+
Rack::CONTENT_LENGTH => "0" }, []]
|
72
76
|
end
|
73
77
|
end
|
74
78
|
end
|
@@ -1,6 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActionDispatch
|
4
|
+
# = Action Dispatch \SSL
|
5
|
+
#
|
4
6
|
# This middleware is added to the stack when <tt>config.force_ssl = true</tt>, and is passed
|
5
7
|
# the options set in +config.ssl_options+. It does three jobs to enforce secure HTTP
|
6
8
|
# requests:
|
@@ -86,7 +88,7 @@ module ActionDispatch
|
|
86
88
|
|
87
89
|
private
|
88
90
|
def set_hsts_header!(headers)
|
89
|
-
headers[
|
91
|
+
headers[Constants::STRICT_TRANSPORT_SECURITY] ||= @hsts_header
|
90
92
|
end
|
91
93
|
|
92
94
|
def normalize_hsts_options(options)
|
@@ -112,23 +114,33 @@ module ActionDispatch
|
|
112
114
|
end
|
113
115
|
|
114
116
|
def flag_cookies_as_secure!(headers)
|
115
|
-
|
116
|
-
|
117
|
+
cookies = headers[Rack::SET_COOKIE]
|
118
|
+
return unless cookies
|
117
119
|
|
118
|
-
|
120
|
+
if Gem::Version.new(Rack::RELEASE) < Gem::Version.new("3")
|
121
|
+
cookies = cookies.split("\n")
|
122
|
+
headers[Rack::SET_COOKIE] = cookies.map { |cookie|
|
119
123
|
if !/;\s*secure\s*(;|$)/i.match?(cookie)
|
120
124
|
"#{cookie}; secure"
|
121
125
|
else
|
122
126
|
cookie
|
123
127
|
end
|
124
128
|
}.join("\n")
|
129
|
+
else
|
130
|
+
headers[Rack::SET_COOKIE] = Array(cookies).map do |cookie|
|
131
|
+
if !/;\s*secure\s*(;|$)/i.match?(cookie)
|
132
|
+
"#{cookie}; secure"
|
133
|
+
else
|
134
|
+
cookie
|
135
|
+
end
|
136
|
+
end
|
125
137
|
end
|
126
138
|
end
|
127
139
|
|
128
140
|
def redirect_to_https(request)
|
129
141
|
[ @redirect.fetch(:status, redirection_status(request)),
|
130
|
-
{
|
131
|
-
|
142
|
+
{ Rack::CONTENT_TYPE => "text/html; charset=utf-8",
|
143
|
+
Constants::LOCATION => https_location_for(request) },
|
132
144
|
(@redirect[:body] || []) ]
|
133
145
|
end
|
134
146
|
|
@@ -4,6 +4,11 @@ require "active_support/inflector/methods"
|
|
4
4
|
require "active_support/dependencies"
|
5
5
|
|
6
6
|
module ActionDispatch
|
7
|
+
# = Action Dispatch \MiddlewareStack
|
8
|
+
#
|
9
|
+
# Read more about {Rails middleware
|
10
|
+
# stack}[https://guides.rubyonrails.org/rails_on_rack.html#action-dispatcher-middleware-stack]
|
11
|
+
# in the guides.
|
7
12
|
class MiddlewareStack
|
8
13
|
class Middleware
|
9
14
|
attr_reader :args, :block, :klass
|
@@ -20,13 +25,13 @@ module ActionDispatch
|
|
20
25
|
case middleware
|
21
26
|
when Middleware
|
22
27
|
klass == middleware.klass
|
23
|
-
when
|
28
|
+
when Module
|
24
29
|
klass == middleware
|
25
30
|
end
|
26
31
|
end
|
27
32
|
|
28
33
|
def inspect
|
29
|
-
if klass.is_a?(
|
34
|
+
if klass.is_a?(Module)
|
30
35
|
klass.to_s
|
31
36
|
else
|
32
37
|
klass.class.to_s
|
@@ -3,10 +3,12 @@
|
|
3
3
|
require "rack/utils"
|
4
4
|
|
5
5
|
module ActionDispatch
|
6
|
+
# = Action Dispatch \Static
|
7
|
+
#
|
6
8
|
# This middleware serves static files from disk, if available.
|
7
9
|
# If no file is found, it hands off to the main app.
|
8
10
|
#
|
9
|
-
# In Rails apps, this middleware is configured to serve assets from
|
11
|
+
# In \Rails apps, this middleware is configured to serve assets from
|
10
12
|
# the +public/+ directory.
|
11
13
|
#
|
12
14
|
# Only GET and HEAD requests are served. POST and other HTTP methods
|
@@ -24,14 +26,16 @@ module ActionDispatch
|
|
24
26
|
end
|
25
27
|
end
|
26
28
|
|
27
|
-
#
|
29
|
+
# = Action Dispatch \FileHandler
|
30
|
+
#
|
31
|
+
# This endpoint serves static files from disk using +Rack::Files+.
|
28
32
|
#
|
29
33
|
# URL paths are matched with static files according to expected
|
30
34
|
# conventions: +path+, +path+.html, +path+/index.html.
|
31
35
|
#
|
32
36
|
# Precompressed versions of these files are checked first. Brotli (.br)
|
33
37
|
# and gzip (.gz) files are supported. If +path+.br exists, this
|
34
|
-
# endpoint returns that file with a <tt>
|
38
|
+
# endpoint returns that file with a <tt>content-encoding: br</tt> header.
|
35
39
|
#
|
36
40
|
# If no matching file is found, this endpoint responds <tt>404 Not Found</tt>.
|
37
41
|
#
|
@@ -53,7 +57,7 @@ module ActionDispatch
|
|
53
57
|
@precompressed = Array(precompressed).map(&:to_s) | %w[ identity ]
|
54
58
|
@compressible_content_types = compressible_content_types
|
55
59
|
|
56
|
-
@file_server = ::Rack::
|
60
|
+
@file_server = ::Rack::Files.new(@root, headers)
|
57
61
|
end
|
58
62
|
|
59
63
|
def call(env)
|
@@ -76,7 +80,7 @@ module ActionDispatch
|
|
76
80
|
request.path_info, ::Rack::Utils.escape_path(filepath).b
|
77
81
|
|
78
82
|
@file_server.call(request.env).tap do |status, headers, body|
|
79
|
-
# Omit
|
83
|
+
# Omit content-encoding/type/etc headers for 304 Not Modified
|
80
84
|
if status != 304
|
81
85
|
headers.update(content_headers)
|
82
86
|
end
|
@@ -104,7 +108,7 @@ module ActionDispatch
|
|
104
108
|
end
|
105
109
|
|
106
110
|
def try_files(filepath, content_type, accept_encoding:)
|
107
|
-
headers = {
|
111
|
+
headers = { Rack::CONTENT_TYPE => content_type }
|
108
112
|
|
109
113
|
if compressible? content_type
|
110
114
|
try_precompressed_files filepath, headers, accept_encoding: accept_encoding
|
@@ -124,10 +128,10 @@ module ActionDispatch
|
|
124
128
|
if content_encoding == "identity"
|
125
129
|
return precompressed_filepath, headers
|
126
130
|
else
|
127
|
-
headers[
|
131
|
+
headers[ActionDispatch::Constants::VARY] = "accept-encoding"
|
128
132
|
|
129
133
|
if accept_encoding.any? { |enc, _| /\b#{content_encoding}\b/i.match?(enc) }
|
130
|
-
headers[
|
134
|
+
headers[ActionDispatch::Constants::CONTENT_ENCODING] = content_encoding
|
131
135
|
return precompressed_filepath, headers
|
132
136
|
end
|
133
137
|
end
|
@@ -1,10 +1,10 @@
|
|
1
|
-
<% actions =
|
1
|
+
<% actions = exception_wrapper.actions %>
|
2
2
|
|
3
3
|
<% if actions.any? %>
|
4
4
|
<div class="actions">
|
5
5
|
<% actions.each do |action, _| %>
|
6
6
|
<%= button_to action, ActionDispatch::ActionableExceptions.endpoint, params: {
|
7
|
-
error:
|
7
|
+
error: exception_wrapper.exception_class_name,
|
8
8
|
action: action,
|
9
9
|
location: request.path
|
10
10
|
} %>
|
@@ -1,11 +1,11 @@
|
|
1
|
-
<% if
|
1
|
+
<% if exception_wrapper.has_corrections? %>
|
2
2
|
<div class="exception-message">
|
3
|
-
<%= simple_format h(
|
3
|
+
<%= simple_format h(exception_wrapper.original_message), { class: "message" }, wrapper_tag: "div" %>
|
4
4
|
</div>
|
5
5
|
<%
|
6
6
|
# The 'did_you_mean' gem can raise exceptions when calling #corrections on
|
7
7
|
# the exception. If it does there are no corrections to show.
|
8
|
-
corrections =
|
8
|
+
corrections = exception_wrapper.corrections rescue []
|
9
9
|
%>
|
10
10
|
<% if corrections.any? %>
|
11
11
|
<b>Did you mean?</b>
|
@@ -17,6 +17,6 @@
|
|
17
17
|
<% end %>
|
18
18
|
<% else %>
|
19
19
|
<div class="exception-message">
|
20
|
-
<%= simple_format h(
|
20
|
+
<%= simple_format h(exception_wrapper.message), { class: "message" }, wrapper_tag: "div" %>
|
21
21
|
</div>
|
22
22
|
<% end %>
|
@@ -18,12 +18,19 @@
|
|
18
18
|
</td>
|
19
19
|
<td width="100%">
|
20
20
|
<pre>
|
21
|
-
<% source_extract[:code].each do |line, source|
|
21
|
+
<% source_extract[:code].each do |line, source| -%>
|
22
|
+
<div class="line<%= " active" if line == source_extract[:line_number] -%>"><% if source.is_a?(Array) -%><%= source[0] -%><span class="error_highlight"><%= source[1] -%></span><%= source[2] -%>
|
23
|
+
<% else -%>
|
24
|
+
<%= source -%>
|
25
|
+
<% end -%></div><% end -%>
|
22
26
|
</pre>
|
23
27
|
</td>
|
24
28
|
</tr>
|
25
29
|
</table>
|
26
30
|
</div>
|
31
|
+
<%- unless self.error_highlight_available? -%>
|
32
|
+
<p class="error_highlight_tip">Tip: You may want to add <code>gem 'error_highlight', '>= 0.4.0'</code> into your Gemfile, which will display the fine-grained error location.</p>
|
33
|
+
<%- end -%>
|
27
34
|
</div>
|
28
35
|
<% end %>
|
29
36
|
<% end %>
|
@@ -1,6 +1,6 @@
|
|
1
1
|
<header>
|
2
2
|
<h1>
|
3
|
-
<%= @
|
3
|
+
<%= @exception_wrapper.exception_class_name %>
|
4
4
|
<% if params_valid? && @request.parameters['controller'] %>
|
5
5
|
in <%= @request.parameters['controller'].camelize %>Controller<% if @request.parameters['action'] %>#<%= @request.parameters['action'] %><% end %>
|
6
6
|
<% end %>
|
@@ -8,24 +8,24 @@
|
|
8
8
|
</header>
|
9
9
|
|
10
10
|
<main role="main" id="container">
|
11
|
-
<%= render "rescues/message_and_suggestions", exception: @exception %>
|
12
|
-
<%= render "rescues/actions", exception: @exception, request: @request %>
|
11
|
+
<%= render "rescues/message_and_suggestions", exception: @exception, exception_wrapper: @exception_wrapper %>
|
12
|
+
<%= render "rescues/actions", exception: @exception, request: @request, exception_wrapper: @exception_wrapper %>
|
13
13
|
|
14
14
|
<%= render "rescues/source", source_extracts: @source_extracts, show_source_idx: @show_source_idx, error_index: 0 %>
|
15
15
|
<%= render "rescues/trace", traces: @traces, trace_to_show: @trace_to_show, error_index: 0 %>
|
16
16
|
|
17
|
-
<% if @
|
17
|
+
<% if @exception_wrapper.has_cause? %>
|
18
18
|
<h2>Exception Causes</h2>
|
19
19
|
<% end %>
|
20
20
|
|
21
21
|
<% @exception_wrapper.wrapped_causes.each.with_index(1) do |wrapper, index| %>
|
22
22
|
<div class="details">
|
23
|
-
<a class="summary" href="#" onclick="return toggle(<%= wrapper.
|
24
|
-
<%= wrapper.
|
23
|
+
<a class="summary" href="#" onclick="return toggle(<%= wrapper.exception_id %>)">
|
24
|
+
<%= wrapper.exception_class_name %>: <%= h wrapper.message %>
|
25
25
|
</a>
|
26
26
|
</div>
|
27
27
|
|
28
|
-
<div id="<%= wrapper.
|
28
|
+
<div id="<%= wrapper.exception_id %>" class="hidden">
|
29
29
|
<%= render "rescues/source", source_extracts: wrapper.source_extracts, show_source_idx: wrapper.source_to_show_id, error_index: index %>
|
30
30
|
<%= render "rescues/trace", traces: wrapper.traces, trace_to_show: wrapper.trace_to_show, error_index: index %>
|
31
31
|
</div>
|
@@ -1,9 +1,9 @@
|
|
1
|
-
<%= @
|
1
|
+
<%= @exception_wrapper.exception_class_name %><%
|
2
2
|
if params_valid? && @request.parameters['controller']
|
3
3
|
%> in <%= @request.parameters['controller'].camelize %>Controller<% if @request.parameters['action'] %>#<%= @request.parameters['action'] %><% end %>
|
4
4
|
<% end %>
|
5
5
|
|
6
|
-
<%= @
|
6
|
+
<%= @exception_wrapper.message %>
|
7
7
|
<%= render template: "rescues/_source" %>
|
8
8
|
<%= render template: "rescues/_trace" %>
|
9
9
|
<%= render template: "rescues/_request_and_response" %>
|
@@ -3,6 +3,7 @@
|
|
3
3
|
<head>
|
4
4
|
<meta charset="utf-8" />
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
6
|
+
<meta name="turbo-visit-control" content="reload">
|
6
7
|
<title>Action Controller: Exception caught</title>
|
7
8
|
<style>
|
8
9
|
body {
|
@@ -148,6 +149,18 @@
|
|
148
149
|
background-color: #FCC;
|
149
150
|
}
|
150
151
|
|
152
|
+
.error_highlight {
|
153
|
+
display: inline-block;
|
154
|
+
background-color: #FF9;
|
155
|
+
text-decoration: #F00 wavy underline;
|
156
|
+
}
|
157
|
+
|
158
|
+
.error_highlight_tip {
|
159
|
+
color: #666;
|
160
|
+
padding: 2px 2px;
|
161
|
+
font-size: 10px;
|
162
|
+
}
|
163
|
+
|
151
164
|
.button_to {
|
152
165
|
display: inline-block;
|
153
166
|
margin-top: 0.75em;
|
@@ -225,6 +238,10 @@
|
|
225
238
|
background-color: #900;
|
226
239
|
}
|
227
240
|
|
241
|
+
.error_highlight {
|
242
|
+
color: #333;
|
243
|
+
}
|
244
|
+
|
228
245
|
input[type="submit"] {
|
229
246
|
box-shadow: 0 3px #800;
|
230
247
|
}
|
@@ -1,19 +1,23 @@
|
|
1
1
|
<header role="banner">
|
2
|
-
<h1>No template for interactive request</h1>
|
2
|
+
<h1>No view template for interactive request</h1>
|
3
3
|
</header>
|
4
4
|
|
5
5
|
<main id="container">
|
6
6
|
<h2><%= h @exception.message %></h2>
|
7
7
|
|
8
|
-
<
|
9
|
-
<
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
8
|
+
<div class="summary">
|
9
|
+
<p>
|
10
|
+
<strong>NOTE:</strong> Rails usually expects a controller action to render a view template with the same name.
|
11
|
+
</p>
|
12
|
+
<p>
|
13
|
+
For example, a <code><%= @exception.controller %>#<%= @exception.action_name %></code> action defined in <code>app/controllers/<%= @exception.controller.controller_path %>_controller.rb</code> should have a corresponding view template
|
14
|
+
in a file named <code>app/views/<%= @exception.controller.controller_name %>/<%= @exception.action_name %>.html.erb</code>.
|
15
|
+
</p>
|
16
|
+
<p>
|
17
|
+
However, if this controller is an API endpoint responding with 204 (No Content), which does not require a view template because it doesn't serve an HTML response, then this error will occur when trying to access it with a browser. In this particular scenario, you can ignore this error.
|
18
|
+
</p>
|
19
|
+
<p>
|
20
|
+
You can find more about view template rendering conventions in the <a href="https://guides.rubyonrails.org/layouts_and_rendering.html#rendering-by-default-convention-over-configuration-in-action">Rails Guides on Layouts and Rendering in Rails</a>.
|
21
|
+
</p>
|
22
|
+
</div>
|
19
23
|
</main>
|
@@ -3,7 +3,7 @@
|
|
3
3
|
</header>
|
4
4
|
|
5
5
|
<main role="main" id="container">
|
6
|
-
<h2><%= h @
|
6
|
+
<h2><%= h @exception_wrapper.message %></h2>
|
7
7
|
|
8
8
|
<%= render "rescues/source", source_extracts: @source_extracts, show_source_idx: @show_source_idx %>
|
9
9
|
<%= render "rescues/trace", traces: @traces, trace_to_show: @trace_to_show %>
|
@@ -2,12 +2,12 @@
|
|
2
2
|
<h1>Routing Error</h1>
|
3
3
|
</header>
|
4
4
|
<main role="main" id="container">
|
5
|
-
<h2><%= h @
|
6
|
-
<% unless @
|
5
|
+
<h2><%= h @exception_wrapper.message %></h2>
|
6
|
+
<% unless @exception_wrapper.failures.empty? %>
|
7
7
|
<p>
|
8
8
|
<h2>Failure reasons:</h2>
|
9
9
|
<ol>
|
10
|
-
<% @
|
10
|
+
<% @exception_wrapper.failures.each do |route, reason| %>
|
11
11
|
<li><code><%= route.inspect.delete('\\') %></code> failed because <%= reason.downcase %></li>
|
12
12
|
<% end %>
|
13
13
|
</ol>
|
@@ -1,19 +1,19 @@
|
|
1
1
|
<header role="banner">
|
2
2
|
<h1>
|
3
|
-
<%= @
|
3
|
+
<%= @exception_wrapper.exception_name %> in
|
4
4
|
<%= @request.parameters["controller"].camelize if @request.parameters["controller"] %>#<%= @request.parameters["action"] %>
|
5
5
|
</h1>
|
6
6
|
</header>
|
7
7
|
|
8
8
|
<main role="main" id="container">
|
9
9
|
<p>
|
10
|
-
Showing <i><%= @
|
10
|
+
Showing <i><%= @exception_wrapper.file_name %></i> where line <b>#<%= @exception_wrapper.line_number %></b> raised:
|
11
11
|
</p>
|
12
|
-
<pre><code><%= h @
|
12
|
+
<pre><code><%= h @exception_wrapper.message %></code></pre>
|
13
13
|
|
14
14
|
<%= render "rescues/source", source_extracts: @source_extracts, show_source_idx: @show_source_idx %>
|
15
15
|
|
16
|
-
<p><%= @
|
16
|
+
<p><%= @exception_wrapper.sub_template_message %></p>
|
17
17
|
|
18
18
|
<%= render "rescues/trace", traces: @traces, trace_to_show: @trace_to_show %>
|
19
19
|
<%= render template: "rescues/_request_and_response" %>
|