actionpack 7.1.5.1 → 8.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +308 -523
- data/README.rdoc +1 -1
- data/lib/abstract_controller/asset_paths.rb +6 -2
- data/lib/abstract_controller/base.rb +104 -105
- data/lib/abstract_controller/caching/fragments.rb +50 -53
- data/lib/abstract_controller/caching.rb +8 -3
- data/lib/abstract_controller/callbacks.rb +70 -62
- data/lib/abstract_controller/collector.rb +7 -7
- data/lib/abstract_controller/deprecator.rb +2 -0
- data/lib/abstract_controller/error.rb +2 -0
- data/lib/abstract_controller/helpers.rb +71 -84
- data/lib/abstract_controller/logger.rb +4 -1
- data/lib/abstract_controller/railties/routes_helpers.rb +2 -0
- data/lib/abstract_controller/rendering.rb +13 -13
- data/lib/abstract_controller/translation.rb +12 -13
- data/lib/abstract_controller/url_for.rb +8 -6
- data/lib/abstract_controller.rb +2 -0
- data/lib/action_controller/api/api_rendering.rb +2 -0
- data/lib/action_controller/api.rb +76 -72
- data/lib/action_controller/base.rb +199 -126
- data/lib/action_controller/caching.rb +16 -14
- data/lib/action_controller/deprecator.rb +2 -0
- data/lib/action_controller/form_builder.rb +21 -18
- data/lib/action_controller/log_subscriber.rb +23 -2
- data/lib/action_controller/metal/allow_browser.rb +133 -0
- data/lib/action_controller/metal/basic_implicit_render.rb +2 -0
- data/lib/action_controller/metal/conditional_get.rb +217 -175
- data/lib/action_controller/metal/content_security_policy.rb +25 -24
- data/lib/action_controller/metal/cookies.rb +4 -2
- data/lib/action_controller/metal/data_streaming.rb +72 -63
- data/lib/action_controller/metal/default_headers.rb +5 -3
- data/lib/action_controller/metal/etag_with_flash.rb +3 -1
- data/lib/action_controller/metal/etag_with_template_digest.rb +17 -15
- data/lib/action_controller/metal/exceptions.rb +16 -9
- data/lib/action_controller/metal/flash.rb +13 -14
- data/lib/action_controller/metal/head.rb +15 -11
- data/lib/action_controller/metal/helpers.rb +63 -55
- data/lib/action_controller/metal/http_authentication.rb +209 -201
- data/lib/action_controller/metal/implicit_render.rb +17 -15
- data/lib/action_controller/metal/instrumentation.rb +16 -14
- data/lib/action_controller/metal/live.rb +177 -128
- data/lib/action_controller/metal/logging.rb +6 -4
- data/lib/action_controller/metal/mime_responds.rb +151 -142
- data/lib/action_controller/metal/parameter_encoding.rb +34 -32
- data/lib/action_controller/metal/params_wrapper.rb +57 -59
- data/lib/action_controller/metal/permissions_policy.rb +22 -12
- data/lib/action_controller/metal/rate_limiting.rb +92 -0
- data/lib/action_controller/metal/redirecting.rb +213 -94
- data/lib/action_controller/metal/renderers.rb +78 -57
- data/lib/action_controller/metal/rendering.rb +111 -77
- data/lib/action_controller/metal/request_forgery_protection.rb +182 -143
- data/lib/action_controller/metal/rescue.rb +20 -9
- data/lib/action_controller/metal/streaming.rb +118 -195
- data/lib/action_controller/metal/strong_parameters.rb +720 -530
- data/lib/action_controller/metal/testing.rb +2 -0
- data/lib/action_controller/metal/url_for.rb +17 -15
- data/lib/action_controller/metal.rb +86 -60
- data/lib/action_controller/railtie.rb +36 -15
- data/lib/action_controller/railties/helpers.rb +2 -0
- data/lib/action_controller/renderer.rb +41 -36
- data/lib/action_controller/structured_event_subscriber.rb +116 -0
- data/lib/action_controller/template_assertions.rb +4 -2
- data/lib/action_controller/test_case.rb +160 -131
- data/lib/action_controller.rb +5 -1
- data/lib/action_dispatch/constants.rb +8 -0
- data/lib/action_dispatch/deprecator.rb +2 -0
- data/lib/action_dispatch/http/cache.rb +163 -35
- data/lib/action_dispatch/http/content_disposition.rb +2 -0
- data/lib/action_dispatch/http/content_security_policy.rb +54 -39
- data/lib/action_dispatch/http/filter_parameters.rb +14 -8
- data/lib/action_dispatch/http/filter_redirect.rb +22 -1
- data/lib/action_dispatch/http/headers.rb +22 -22
- data/lib/action_dispatch/http/mime_negotiation.rb +89 -41
- data/lib/action_dispatch/http/mime_type.rb +25 -21
- data/lib/action_dispatch/http/mime_types.rb +3 -0
- data/lib/action_dispatch/http/param_builder.rb +187 -0
- data/lib/action_dispatch/http/param_error.rb +26 -0
- data/lib/action_dispatch/http/parameters.rb +14 -12
- data/lib/action_dispatch/http/permissions_policy.rb +25 -36
- data/lib/action_dispatch/http/query_parser.rb +55 -0
- data/lib/action_dispatch/http/rack_cache.rb +2 -0
- data/lib/action_dispatch/http/request.rb +141 -92
- data/lib/action_dispatch/http/response.rb +137 -77
- data/lib/action_dispatch/http/upload.rb +18 -16
- data/lib/action_dispatch/http/url.rb +187 -89
- data/lib/action_dispatch/journey/formatter.rb +21 -9
- data/lib/action_dispatch/journey/gtg/builder.rb +4 -3
- data/lib/action_dispatch/journey/gtg/simulator.rb +34 -11
- data/lib/action_dispatch/journey/gtg/transition_table.rb +47 -53
- data/lib/action_dispatch/journey/nfa/dot.rb +2 -0
- data/lib/action_dispatch/journey/nodes/node.rb +8 -6
- data/lib/action_dispatch/journey/parser.rb +99 -195
- data/lib/action_dispatch/journey/path/pattern.rb +4 -1
- data/lib/action_dispatch/journey/route.rb +54 -38
- data/lib/action_dispatch/journey/router/utils.rb +22 -27
- data/lib/action_dispatch/journey/router.rb +63 -83
- data/lib/action_dispatch/journey/routes.rb +11 -2
- data/lib/action_dispatch/journey/scanner.rb +46 -42
- data/lib/action_dispatch/journey/visitors.rb +57 -23
- data/lib/action_dispatch/journey/visualizer/fsm.js +4 -6
- data/lib/action_dispatch/journey.rb +2 -0
- data/lib/action_dispatch/log_subscriber.rb +7 -1
- data/lib/action_dispatch/middleware/actionable_exceptions.rb +2 -0
- data/lib/action_dispatch/middleware/assume_ssl.rb +8 -5
- data/lib/action_dispatch/middleware/callbacks.rb +3 -1
- data/lib/action_dispatch/middleware/cookies.rb +125 -106
- data/lib/action_dispatch/middleware/debug_exceptions.rb +37 -8
- data/lib/action_dispatch/middleware/debug_locks.rb +15 -13
- data/lib/action_dispatch/middleware/debug_view.rb +13 -5
- data/lib/action_dispatch/middleware/exception_wrapper.rb +18 -23
- data/lib/action_dispatch/middleware/executor.rb +19 -4
- data/lib/action_dispatch/middleware/flash.rb +63 -51
- data/lib/action_dispatch/middleware/host_authorization.rb +17 -15
- data/lib/action_dispatch/middleware/public_exceptions.rb +14 -12
- data/lib/action_dispatch/middleware/reloader.rb +5 -3
- data/lib/action_dispatch/middleware/remote_ip.rb +87 -77
- data/lib/action_dispatch/middleware/request_id.rb +16 -10
- data/lib/action_dispatch/middleware/server_timing.rb +4 -2
- data/lib/action_dispatch/middleware/session/abstract_store.rb +2 -0
- data/lib/action_dispatch/middleware/session/cache_store.rb +30 -8
- data/lib/action_dispatch/middleware/session/cookie_store.rb +27 -26
- data/lib/action_dispatch/middleware/session/mem_cache_store.rb +7 -3
- data/lib/action_dispatch/middleware/show_exceptions.rb +16 -16
- data/lib/action_dispatch/middleware/ssl.rb +53 -40
- data/lib/action_dispatch/middleware/stack.rb +11 -10
- data/lib/action_dispatch/middleware/static.rb +33 -31
- data/lib/action_dispatch/middleware/templates/rescues/_copy_button.html.erb +1 -0
- data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +3 -5
- data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +9 -5
- data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +1 -0
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +1 -0
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +4 -0
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +3 -0
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +50 -0
- data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +1 -0
- data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +1 -0
- data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +1 -0
- data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +1 -0
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +1 -0
- data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +1 -1
- data/lib/action_dispatch/railtie.rb +23 -3
- data/lib/action_dispatch/request/session.rb +24 -21
- data/lib/action_dispatch/request/utils.rb +11 -3
- data/lib/action_dispatch/routing/endpoint.rb +2 -0
- data/lib/action_dispatch/routing/inspector.rb +85 -60
- data/lib/action_dispatch/routing/mapper.rb +1031 -851
- data/lib/action_dispatch/routing/polymorphic_routes.rb +69 -62
- data/lib/action_dispatch/routing/redirection.rb +47 -39
- data/lib/action_dispatch/routing/route_set.rb +79 -56
- data/lib/action_dispatch/routing/routes_proxy.rb +7 -4
- data/lib/action_dispatch/routing/url_for.rb +130 -125
- data/lib/action_dispatch/routing.rb +150 -148
- data/lib/action_dispatch/structured_event_subscriber.rb +20 -0
- data/lib/action_dispatch/system_test_case.rb +91 -81
- data/lib/action_dispatch/system_testing/browser.rb +16 -23
- data/lib/action_dispatch/system_testing/driver.rb +2 -0
- data/lib/action_dispatch/system_testing/server.rb +2 -0
- data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +34 -23
- data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +2 -0
- data/lib/action_dispatch/testing/assertion_response.rb +9 -7
- data/lib/action_dispatch/testing/assertions/response.rb +52 -25
- data/lib/action_dispatch/testing/assertions/routing.rb +168 -87
- data/lib/action_dispatch/testing/assertions.rb +2 -0
- data/lib/action_dispatch/testing/integration.rb +233 -223
- data/lib/action_dispatch/testing/request_encoder.rb +11 -9
- data/lib/action_dispatch/testing/test_helpers/page_dump_helper.rb +35 -0
- data/lib/action_dispatch/testing/test_process.rb +11 -8
- data/lib/action_dispatch/testing/test_request.rb +3 -1
- data/lib/action_dispatch/testing/test_response.rb +27 -26
- data/lib/action_dispatch.rb +36 -32
- data/lib/action_pack/gem_version.rb +6 -4
- data/lib/action_pack/version.rb +3 -1
- data/lib/action_pack.rb +17 -16
- metadata +36 -32
- data/lib/action_dispatch/journey/parser.y +0 -50
- data/lib/action_dispatch/journey/parser_extras.rb +0 -31
|
@@ -1,57 +1,70 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
# :markup: markdown
|
|
4
|
+
|
|
3
5
|
module ActionDispatch
|
|
4
|
-
#
|
|
6
|
+
# # Action Dispatch SSL
|
|
7
|
+
#
|
|
8
|
+
# This middleware is added to the stack when `config.force_ssl = true`, and is
|
|
9
|
+
# passed the options set in `config.ssl_options`. It does three jobs to enforce
|
|
10
|
+
# secure HTTP requests:
|
|
11
|
+
#
|
|
12
|
+
# 1. **TLS redirect**: Permanently redirects `http://` requests to `https://`
|
|
13
|
+
# with the same URL host, path, etc. Enabled by default. Set
|
|
14
|
+
# `config.ssl_options` to modify the destination URL:
|
|
15
|
+
#
|
|
16
|
+
# config.ssl_options = { redirect: { host: "secure.widgets.com", port: 8080 }`
|
|
5
17
|
#
|
|
6
|
-
#
|
|
7
|
-
# the options set in +config.ssl_options+. It does three jobs to enforce secure HTTP
|
|
8
|
-
# requests:
|
|
18
|
+
# Or set `redirect: false` to disable redirection.
|
|
9
19
|
#
|
|
10
|
-
#
|
|
11
|
-
# with the same URL host, path, etc. Enabled by default. Set +config.ssl_options+
|
|
12
|
-
# to modify the destination URL
|
|
13
|
-
# (e.g. <tt>redirect: { host: "secure.widgets.com", port: 8080 }</tt>), or set
|
|
14
|
-
# <tt>redirect: false</tt> to disable this feature.
|
|
20
|
+
# Requests can opt-out of redirection with `exclude`:
|
|
15
21
|
#
|
|
16
|
-
#
|
|
22
|
+
# config.ssl_options = { redirect: { exclude: -> request { request.path == "/up" } } }
|
|
17
23
|
#
|
|
18
|
-
#
|
|
24
|
+
# Cookies will not be flagged as secure for excluded requests.
|
|
19
25
|
#
|
|
20
|
-
#
|
|
26
|
+
# When proxying through a load balancer that terminates SSL, the forwarded
|
|
27
|
+
# request will appear as though it's HTTP instead of HTTPS to the application.
|
|
28
|
+
# This makes redirects and cookie security target HTTP instead of HTTPS.
|
|
29
|
+
# To make the server assume that the proxy already terminated SSL, and
|
|
30
|
+
# that the request really is HTTPS, set `config.assume_ssl` to `true`:
|
|
21
31
|
#
|
|
22
|
-
#
|
|
23
|
-
# must not be sent along with +http://+ requests. Enabled by default. Set
|
|
24
|
-
# +config.ssl_options+ with <tt>secure_cookies: false</tt> to disable this feature.
|
|
32
|
+
# config.assume_ssl = true
|
|
25
33
|
#
|
|
26
|
-
#
|
|
27
|
-
#
|
|
28
|
-
#
|
|
34
|
+
# 2. **Secure cookies**: Sets the `secure` flag on cookies to tell browsers
|
|
35
|
+
# they must not be sent along with `http://` requests. Enabled by default.
|
|
36
|
+
# Set `config.ssl_options` with `secure_cookies: false` to disable this
|
|
37
|
+
# feature.
|
|
29
38
|
#
|
|
30
|
-
#
|
|
39
|
+
# 3. **HTTP Strict Transport Security (HSTS)**: Tells the browser to remember
|
|
40
|
+
# this site as TLS-only and automatically redirect non-TLS requests. Enabled
|
|
41
|
+
# by default. Configure `config.ssl_options` with `hsts: false` to disable.
|
|
31
42
|
#
|
|
32
|
-
#
|
|
33
|
-
# required to qualify for browser preload lists is 1 year. Defaults to
|
|
34
|
-
# 2 years (recommended).
|
|
43
|
+
# Set `config.ssl_options` with `hsts: { ... }` to configure HSTS:
|
|
35
44
|
#
|
|
36
|
-
#
|
|
37
|
-
#
|
|
38
|
-
#
|
|
45
|
+
# * `expires`: How long, in seconds, these settings will stick. The
|
|
46
|
+
# minimum required to qualify for browser preload lists is 1 year.
|
|
47
|
+
# Defaults to 2 years (recommended).
|
|
39
48
|
#
|
|
40
|
-
#
|
|
41
|
-
#
|
|
42
|
-
#
|
|
43
|
-
#
|
|
44
|
-
#
|
|
45
|
-
#
|
|
49
|
+
# * `subdomains`: Set to `true` to tell the browser to apply these
|
|
50
|
+
# settings to all subdomains. This protects your cookies from
|
|
51
|
+
# interception by a vulnerable site on a subdomain. Defaults to `true`.
|
|
52
|
+
#
|
|
53
|
+
# * `preload`: Advertise that this site may be included in browsers'
|
|
54
|
+
# preloaded HSTS lists. HSTS protects your site on every visit *except
|
|
55
|
+
# the first visit* since it hasn't seen your HSTS header yet. To close
|
|
56
|
+
# this gap, browser vendors include a baked-in list of HSTS-enabled
|
|
57
|
+
# sites. Go to https://hstspreload.org to submit your site for
|
|
58
|
+
# inclusion. Defaults to `false`.
|
|
59
|
+
#
|
|
60
|
+
#
|
|
61
|
+
# To turn off HSTS, omitting the header is not enough. Browsers will
|
|
62
|
+
# remember the original HSTS directive until it expires. Instead, use the
|
|
63
|
+
# header to tell browsers to expire HSTS immediately. Setting `hsts: false`
|
|
64
|
+
# is a shortcut for `hsts: { expires: 0 }`.
|
|
46
65
|
#
|
|
47
|
-
# To turn off HSTS, omitting the header is not enough. Browsers will remember the
|
|
48
|
-
# original HSTS directive until it expires. Instead, use the header to tell browsers to
|
|
49
|
-
# expire HSTS immediately. Setting <tt>hsts: false</tt> is a shortcut for
|
|
50
|
-
# <tt>hsts: { expires: 0 }</tt>.
|
|
51
66
|
class SSL
|
|
52
|
-
# :stopdoc:
|
|
53
|
-
|
|
54
|
-
# Default to 2 years as recommended on hstspreload.org.
|
|
67
|
+
# :stopdoc: Default to 2 years as recommended on hstspreload.org.
|
|
55
68
|
HSTS_EXPIRES_IN = 63072000
|
|
56
69
|
|
|
57
70
|
PERMANENT_REDIRECT_REQUEST_METHODS = %w[GET HEAD] # :nodoc:
|
|
@@ -93,8 +106,8 @@ module ActionDispatch
|
|
|
93
106
|
|
|
94
107
|
def normalize_hsts_options(options)
|
|
95
108
|
case options
|
|
96
|
-
# Explicitly disabling HSTS clears the existing setting from browsers
|
|
97
|
-
#
|
|
109
|
+
# Explicitly disabling HSTS clears the existing setting from browsers by setting
|
|
110
|
+
# expiry to 0.
|
|
98
111
|
when false
|
|
99
112
|
self.class.default_hsts_options.merge(expires: 0)
|
|
100
113
|
# Default to enabled, with default options.
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
# :markup: markdown
|
|
4
|
+
|
|
3
5
|
require "active_support/inflector/methods"
|
|
4
6
|
require "active_support/dependencies"
|
|
5
7
|
|
|
6
8
|
module ActionDispatch
|
|
7
|
-
#
|
|
9
|
+
# # Action Dispatch MiddlewareStack
|
|
8
10
|
#
|
|
9
|
-
# Read more about
|
|
10
|
-
# stack
|
|
11
|
+
# Read more about [Rails middleware
|
|
12
|
+
# stack](https://guides.rubyonrails.org/rails_on_rack.html#action-dispatcher-middleware-stack)
|
|
11
13
|
# in the guides.
|
|
12
14
|
class MiddlewareStack
|
|
13
15
|
class Middleware
|
|
@@ -47,9 +49,8 @@ module ActionDispatch
|
|
|
47
49
|
end
|
|
48
50
|
end
|
|
49
51
|
|
|
50
|
-
# This class is used to instrument the execution of a single middleware.
|
|
51
|
-
#
|
|
52
|
-
# call.
|
|
52
|
+
# This class is used to instrument the execution of a single middleware. It
|
|
53
|
+
# proxies the `call` method transparently and instruments the method call.
|
|
53
54
|
class InstrumentationProxy
|
|
54
55
|
EVENT_NAME = "process_middleware.action_dispatch"
|
|
55
56
|
|
|
@@ -125,16 +126,16 @@ module ActionDispatch
|
|
|
125
126
|
|
|
126
127
|
# Deletes a middleware from the middleware stack.
|
|
127
128
|
#
|
|
128
|
-
# Returns the array of middlewares not including the deleted item, or
|
|
129
|
-
#
|
|
129
|
+
# Returns the array of middlewares not including the deleted item, or returns
|
|
130
|
+
# nil if the target is not found.
|
|
130
131
|
def delete(target)
|
|
131
132
|
middlewares.reject! { |m| m.name == target.name }
|
|
132
133
|
end
|
|
133
134
|
|
|
134
135
|
# Deletes a middleware from the middleware stack.
|
|
135
136
|
#
|
|
136
|
-
# Returns the array of middlewares not including the deleted item, or
|
|
137
|
-
#
|
|
137
|
+
# Returns the array of middlewares not including the deleted item, or raises
|
|
138
|
+
# `RuntimeError` if the target is not found.
|
|
138
139
|
def delete!(target)
|
|
139
140
|
delete(target) || (raise "No such middleware to remove: #{target.inspect}")
|
|
140
141
|
end
|
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
# :markup: markdown
|
|
4
|
+
|
|
3
5
|
require "rack/utils"
|
|
4
6
|
|
|
5
7
|
module ActionDispatch
|
|
6
|
-
#
|
|
8
|
+
# # Action Dispatch Static
|
|
7
9
|
#
|
|
8
|
-
# This middleware serves static files from disk, if available.
|
|
9
|
-
#
|
|
10
|
+
# This middleware serves static files from disk, if available. If no file is
|
|
11
|
+
# found, it hands off to the main app.
|
|
10
12
|
#
|
|
11
|
-
# In
|
|
12
|
-
#
|
|
13
|
+
# In Rails apps, this middleware is configured to serve assets from the
|
|
14
|
+
# `public/` directory.
|
|
13
15
|
#
|
|
14
|
-
# Only GET and HEAD requests are served. POST and other HTTP methods
|
|
15
|
-
#
|
|
16
|
+
# Only GET and HEAD requests are served. POST and other HTTP methods are handed
|
|
17
|
+
# off to the main app.
|
|
16
18
|
#
|
|
17
19
|
# Only files in the root directory are served; path traversal is denied.
|
|
18
20
|
class Static
|
|
@@ -26,31 +28,31 @@ module ActionDispatch
|
|
|
26
28
|
end
|
|
27
29
|
end
|
|
28
30
|
|
|
29
|
-
#
|
|
31
|
+
# # Action Dispatch FileHandler
|
|
30
32
|
#
|
|
31
|
-
# This endpoint serves static files from disk using
|
|
33
|
+
# This endpoint serves static files from disk using `Rack::Files`.
|
|
32
34
|
#
|
|
33
|
-
# URL paths are matched with static files according to expected
|
|
34
|
-
#
|
|
35
|
+
# URL paths are matched with static files according to expected conventions:
|
|
36
|
+
# `path`, `path`.html, `path`/index.html.
|
|
35
37
|
#
|
|
36
|
-
# Precompressed versions of these files are checked first. Brotli (.br)
|
|
37
|
-
#
|
|
38
|
-
#
|
|
38
|
+
# Precompressed versions of these files are checked first. Brotli (.br) and gzip
|
|
39
|
+
# (.gz) files are supported. If `path`.br exists, this endpoint returns that
|
|
40
|
+
# file with a `content-encoding: br` header.
|
|
39
41
|
#
|
|
40
|
-
# If no matching file is found, this endpoint responds
|
|
42
|
+
# If no matching file is found, this endpoint responds `404 Not Found`.
|
|
41
43
|
#
|
|
42
|
-
# Pass the
|
|
43
|
-
#
|
|
44
|
-
#
|
|
44
|
+
# Pass the `root` directory to search for matching files, an optional `index:
|
|
45
|
+
# "index"` to change the default `path`/index.html, and optional additional
|
|
46
|
+
# response headers.
|
|
45
47
|
class FileHandler
|
|
46
|
-
#
|
|
48
|
+
# `Accept-Encoding` value -> file extension
|
|
47
49
|
PRECOMPRESSED = {
|
|
48
50
|
"br" => ".br",
|
|
49
51
|
"gzip" => ".gz",
|
|
50
52
|
"identity" => nil
|
|
51
53
|
}
|
|
52
54
|
|
|
53
|
-
def initialize(root, index: "index", headers: {}, precompressed: %i[ br gzip ], compressible_content_types: /\A(?:text\/|application\/javascript)/)
|
|
55
|
+
def initialize(root, index: "index", headers: {}, precompressed: %i[ br gzip ], compressible_content_types: /\A(?:text\/|application\/javascript|image\/svg\+xml)/)
|
|
54
56
|
@root = root.chomp("/").b
|
|
55
57
|
@index = index
|
|
56
58
|
|
|
@@ -91,11 +93,11 @@ module ActionDispatch
|
|
|
91
93
|
|
|
92
94
|
# Match a URI path to a static file to be served.
|
|
93
95
|
#
|
|
94
|
-
# Used by the
|
|
95
|
-
#
|
|
96
|
+
# Used by the `Static` class to negotiate a servable file in the `public/`
|
|
97
|
+
# directory (see Static#call).
|
|
96
98
|
#
|
|
97
|
-
# Checks for
|
|
98
|
-
#
|
|
99
|
+
# Checks for `path`, `path`.html, and `path`/index.html files, in that order,
|
|
100
|
+
# including .br and .gzip compressed extensions.
|
|
99
101
|
#
|
|
100
102
|
# If a matching file is found, the path and necessary response headers
|
|
101
103
|
# (Content-Type, Content-Encoding) are returned.
|
|
@@ -120,11 +122,11 @@ module ActionDispatch
|
|
|
120
122
|
def try_precompressed_files(filepath, headers, accept_encoding:)
|
|
121
123
|
each_precompressed_filepath(filepath) do |content_encoding, precompressed_filepath|
|
|
122
124
|
if file_readable? precompressed_filepath
|
|
123
|
-
# Identity encoding is default, so we skip Accept-Encoding
|
|
124
|
-
#
|
|
125
|
+
# Identity encoding is default, so we skip Accept-Encoding negotiation and
|
|
126
|
+
# needn't set Content-Encoding.
|
|
125
127
|
#
|
|
126
|
-
# Vary header is expected when we've found other available
|
|
127
|
-
#
|
|
128
|
+
# Vary header is expected when we've found other available encodings that
|
|
129
|
+
# Accept-Encoding ruled out.
|
|
128
130
|
if content_encoding == "identity"
|
|
129
131
|
return precompressed_filepath, headers
|
|
130
132
|
else
|
|
@@ -164,9 +166,9 @@ module ActionDispatch
|
|
|
164
166
|
content_type = ::Rack::Mime.mime_type(ext, nil)
|
|
165
167
|
yield path, content_type || "text/plain"
|
|
166
168
|
|
|
167
|
-
# Tack on .html and /index.html only for paths that don't have
|
|
168
|
-
#
|
|
169
|
-
#
|
|
169
|
+
# Tack on .html and /index.html only for paths that don't have an explicit,
|
|
170
|
+
# resolvable file extension. No need to check for foo.js.html and
|
|
171
|
+
# foo.js/index.html.
|
|
170
172
|
unless content_type
|
|
171
173
|
default_ext = ::ActionController::Base.default_static_extension
|
|
172
174
|
if ext != default_ext
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<button onclick="copyAsText.bind(this)()">Copy as text</button>
|
|
@@ -11,8 +11,9 @@
|
|
|
11
11
|
<tr>
|
|
12
12
|
<td>
|
|
13
13
|
<pre class="line_numbers">
|
|
14
|
-
<% source_extract[:code].each_key do |
|
|
15
|
-
|
|
14
|
+
<% source_extract[:code].each_key do |line| %>
|
|
15
|
+
<% file_url = editor_url(source_extract[:trace], line: line) %>
|
|
16
|
+
<span><%= link_to_if file_url, line, file_url -%></span>
|
|
16
17
|
<% end %>
|
|
17
18
|
</pre>
|
|
18
19
|
</td>
|
|
@@ -28,9 +29,6 @@
|
|
|
28
29
|
</tr>
|
|
29
30
|
</table>
|
|
30
31
|
</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 -%>
|
|
34
32
|
</div>
|
|
35
33
|
<% end %>
|
|
36
34
|
<% end %>
|
|
@@ -13,13 +13,17 @@
|
|
|
13
13
|
<% end %>
|
|
14
14
|
|
|
15
15
|
<% traces.each do |name, trace| %>
|
|
16
|
-
<div id="<%= "#{name.gsub(/\s/, '-')}-#{error_index}" %>" style="display: <%= (name == trace_to_show) ? 'block' : 'none' %>;">
|
|
16
|
+
<div id="<%= "#{name.gsub(/\s/, '-')}-#{error_index}" %>" class="trace-container" style="display: <%= (name == trace_to_show) ? 'block' : 'none' %>;">
|
|
17
17
|
<code class="traces">
|
|
18
18
|
<% trace.each do |frame| %>
|
|
19
|
-
<
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
<div class="trace">
|
|
20
|
+
<% file_url = editor_url(frame[:trace]) %>
|
|
21
|
+
<%= file_url && link_to("✏️", file_url, class: "edit-icon") %>
|
|
22
|
+
<a class="trace-frames trace-frames-<%= error_index %>" data-exception-object-id="<%= frame[:exception_object_id] %>" data-frame-id="<%= frame[:id] %>" href="#">
|
|
23
|
+
<%= frame[:trace] %>
|
|
24
|
+
</a>
|
|
25
|
+
<br>
|
|
26
|
+
</div>
|
|
23
27
|
<% end %>
|
|
24
28
|
</code>
|
|
25
29
|
</div>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<header role="banner">
|
|
2
|
+
<%= render "rescues/copy_button" %>
|
|
2
3
|
<h1>
|
|
3
4
|
<%= @exception.class.to_s %>
|
|
4
5
|
<% if @request.parameters['controller'] %>
|
|
@@ -10,6 +11,9 @@
|
|
|
10
11
|
<main role="main" id="container">
|
|
11
12
|
<h2>
|
|
12
13
|
<%= h @exception.message %>
|
|
14
|
+
<% if defined?(ActionText) && @exception.message.match?(%r{#{ActionText::RichText.table_name}}) %>
|
|
15
|
+
<br />To resolve this issue run: bin/rails action_text:install
|
|
16
|
+
<% end %>
|
|
13
17
|
<% if defined?(ActiveStorage) && @exception.message.match?(%r{#{ActiveStorage::Blob.table_name}|#{ActiveStorage::Attachment.table_name}}) %>
|
|
14
18
|
<br />To resolve this issue run: bin/rails active_storage:install
|
|
15
19
|
<% end %>
|
|
@@ -4,6 +4,9 @@
|
|
|
4
4
|
<% end %>
|
|
5
5
|
|
|
6
6
|
<%= @exception.message %>
|
|
7
|
+
<% if defined?(ActionText) && @exception.message.match?(%r{#{ActionText::RichText.table_name}}) %>
|
|
8
|
+
To resolve this issue run: bin/rails action_text:install
|
|
9
|
+
<% end %>
|
|
7
10
|
<% if defined?(ActiveStorage) && @exception.message.match?(%r{#{ActiveStorage::Blob.table_name}|#{ActiveStorage::Attachment.table_name}}) %>
|
|
8
11
|
To resolve this issue run: bin/rails active_storage:install
|
|
9
12
|
<% end %>
|
|
@@ -38,6 +38,22 @@
|
|
|
38
38
|
padding: 0.5em 1.5em;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
header button {
|
|
42
|
+
appearance: none;
|
|
43
|
+
background-color: hsl(0 0% 0% / 0.2);
|
|
44
|
+
border: 0;
|
|
45
|
+
border-radius: 14px;
|
|
46
|
+
color: white;
|
|
47
|
+
float: right;
|
|
48
|
+
font-weight: 500;
|
|
49
|
+
height: 28px;
|
|
50
|
+
padding-inline: 14px;
|
|
51
|
+
margin: 0.35em 0;
|
|
52
|
+
}
|
|
53
|
+
header button:active {
|
|
54
|
+
background-color: hsl(0 0% 0% / 0.25);
|
|
55
|
+
}
|
|
56
|
+
|
|
41
57
|
h1 {
|
|
42
58
|
overflow-wrap: break-word;
|
|
43
59
|
margin: 0.2em 0;
|
|
@@ -54,6 +70,30 @@
|
|
|
54
70
|
font-size: 11px;
|
|
55
71
|
}
|
|
56
72
|
|
|
73
|
+
.trace-container {
|
|
74
|
+
margin-top: 10px;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
code.traces .trace {
|
|
78
|
+
display: flex;
|
|
79
|
+
align-items: center;
|
|
80
|
+
gap: 2px;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.edit-icon {
|
|
84
|
+
width: 16px;
|
|
85
|
+
height: 16px;
|
|
86
|
+
display: flex;
|
|
87
|
+
font-size: 13px;
|
|
88
|
+
align-items: center;
|
|
89
|
+
justify-content: center;
|
|
90
|
+
text-decoration: none;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.edit-icon:hover {
|
|
94
|
+
scale: 1.05;
|
|
95
|
+
}
|
|
96
|
+
|
|
57
97
|
.response-heading, .request-heading {
|
|
58
98
|
margin-top: 30px;
|
|
59
99
|
}
|
|
@@ -274,11 +314,21 @@
|
|
|
274
314
|
var toggleEnvDump = function() {
|
|
275
315
|
return toggle('env_dump');
|
|
276
316
|
}
|
|
317
|
+
var copyAsText = function() {
|
|
318
|
+
const text = document.getElementById("exception-message-for-copy").textContent;
|
|
319
|
+
|
|
320
|
+
navigator.clipboard.writeText(text).then(() => {
|
|
321
|
+
const beforeText = this.innerText;
|
|
322
|
+
this.innerText = "Copied!"
|
|
323
|
+
setTimeout(() => this.innerText = beforeText, 1000)
|
|
324
|
+
})
|
|
325
|
+
}
|
|
277
326
|
</script>
|
|
278
327
|
</head>
|
|
279
328
|
<body>
|
|
280
329
|
|
|
281
330
|
<%= yield %>
|
|
331
|
+
<script type="text/plain" id="exception-message-for-copy"><%= raw @exception_message_for_copy %></script>
|
|
282
332
|
|
|
283
333
|
</body>
|
|
284
334
|
</html>
|
|
@@ -158,7 +158,7 @@
|
|
|
158
158
|
function buildTr(string) {
|
|
159
159
|
var tr = document.createElement('tr');
|
|
160
160
|
var th = document.createElement('th');
|
|
161
|
-
th.setAttribute('colspan',
|
|
161
|
+
th.setAttribute('colspan', 5);
|
|
162
162
|
tr.appendChild(th);
|
|
163
163
|
th.innerText = string;
|
|
164
164
|
return tr;
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
# :markup: markdown
|
|
4
|
+
|
|
3
5
|
require "action_dispatch"
|
|
4
6
|
require "action_dispatch/log_subscriber"
|
|
7
|
+
require "action_dispatch/structured_event_subscriber"
|
|
5
8
|
require "active_support/messages/rotation_configuration"
|
|
9
|
+
require "rails/railtie"
|
|
6
10
|
|
|
7
11
|
module ActionDispatch
|
|
8
12
|
class Railtie < Rails::Railtie # :nodoc:
|
|
@@ -27,6 +31,11 @@ module ActionDispatch
|
|
|
27
31
|
config.action_dispatch.request_id_header = ActionDispatch::Constants::X_REQUEST_ID
|
|
28
32
|
config.action_dispatch.log_rescued_responses = true
|
|
29
33
|
config.action_dispatch.debug_exception_log_level = :fatal
|
|
34
|
+
config.action_dispatch.strict_freshness = false
|
|
35
|
+
|
|
36
|
+
config.action_dispatch.ignore_leading_brackets = nil
|
|
37
|
+
config.action_dispatch.strict_query_string_separator = nil
|
|
38
|
+
config.action_dispatch.verbose_redirect_logs = false
|
|
30
39
|
|
|
31
40
|
config.action_dispatch.default_headers = {
|
|
32
41
|
"X-Frame-Options" => "SAMEORIGIN",
|
|
@@ -49,11 +58,21 @@ module ActionDispatch
|
|
|
49
58
|
ActionDispatch::Http::URL.secure_protocol = app.config.force_ssl
|
|
50
59
|
ActionDispatch::Http::URL.tld_length = app.config.action_dispatch.tld_length
|
|
51
60
|
|
|
61
|
+
unless app.config.action_dispatch.domain_extractor.nil?
|
|
62
|
+
ActionDispatch::Http::URL.domain_extractor = app.config.action_dispatch.domain_extractor
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
unless app.config.action_dispatch.ignore_leading_brackets.nil?
|
|
66
|
+
ActionDispatch::ParamBuilder.ignore_leading_brackets = app.config.action_dispatch.ignore_leading_brackets
|
|
67
|
+
end
|
|
68
|
+
unless app.config.action_dispatch.strict_query_string_separator.nil?
|
|
69
|
+
ActionDispatch::QueryParser.strict_query_string_separator = app.config.action_dispatch.strict_query_string_separator
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
ActionDispatch.verbose_redirect_logs = app.config.action_dispatch.verbose_redirect_logs
|
|
73
|
+
|
|
52
74
|
ActiveSupport.on_load(:action_dispatch_request) do
|
|
53
75
|
self.ignore_accept_header = app.config.action_dispatch.ignore_accept_header
|
|
54
|
-
unless app.config.action_dispatch.respond_to?(:return_only_request_media_type_on_content_type)
|
|
55
|
-
self.return_only_media_type_on_content_type = app.config.action_dispatch.return_only_request_media_type_on_content_type
|
|
56
|
-
end
|
|
57
76
|
ActionDispatch::Request::Utils.perform_deep_munge = app.config.action_dispatch.perform_deep_munge
|
|
58
77
|
end
|
|
59
78
|
|
|
@@ -70,6 +89,7 @@ module ActionDispatch
|
|
|
70
89
|
|
|
71
90
|
ActionDispatch::Routing::Mapper.route_source_locations = Rails.env.development?
|
|
72
91
|
|
|
92
|
+
ActionDispatch::Http::Cache::Request.strict_freshness = app.config.action_dispatch.strict_freshness
|
|
73
93
|
ActionDispatch.test_app = app
|
|
74
94
|
end
|
|
75
95
|
end
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
# :markup: markdown
|
|
4
|
+
|
|
3
5
|
require "rack/session/abstract/id"
|
|
4
6
|
|
|
5
7
|
module ActionDispatch
|
|
@@ -107,8 +109,8 @@ module ActionDispatch
|
|
|
107
109
|
end
|
|
108
110
|
end
|
|
109
111
|
|
|
110
|
-
# Returns value of the key stored in the session or
|
|
111
|
-
#
|
|
112
|
+
# Returns value of the key stored in the session or `nil` if the given key is
|
|
113
|
+
# not found in the session.
|
|
112
114
|
def [](key)
|
|
113
115
|
load_for_read!
|
|
114
116
|
key = key.to_s
|
|
@@ -120,8 +122,8 @@ module ActionDispatch
|
|
|
120
122
|
end
|
|
121
123
|
end
|
|
122
124
|
|
|
123
|
-
# Returns the nested value specified by the sequence of keys, returning
|
|
124
|
-
#
|
|
125
|
+
# Returns the nested value specified by the sequence of keys, returning `nil` if
|
|
126
|
+
# any intermediate step is `nil`.
|
|
125
127
|
def dig(*keys)
|
|
126
128
|
load_for_read!
|
|
127
129
|
keys = keys.map.with_index { |key, i| i.zero? ? key.to_s : key }
|
|
@@ -153,6 +155,7 @@ module ActionDispatch
|
|
|
153
155
|
load_for_write!
|
|
154
156
|
@delegate[key.to_s] = value
|
|
155
157
|
end
|
|
158
|
+
alias store []=
|
|
156
159
|
|
|
157
160
|
# Clears the session.
|
|
158
161
|
def clear
|
|
@@ -169,14 +172,14 @@ module ActionDispatch
|
|
|
169
172
|
|
|
170
173
|
# Updates the session with given Hash.
|
|
171
174
|
#
|
|
172
|
-
#
|
|
173
|
-
#
|
|
175
|
+
# session.to_hash
|
|
176
|
+
# # => {"session_id"=>"e29b9ea315edf98aad94cc78c34cc9b2"}
|
|
174
177
|
#
|
|
175
|
-
#
|
|
176
|
-
#
|
|
178
|
+
# session.update({ "foo" => "bar" })
|
|
179
|
+
# # => {"session_id"=>"e29b9ea315edf98aad94cc78c34cc9b2", "foo" => "bar"}
|
|
177
180
|
#
|
|
178
|
-
#
|
|
179
|
-
#
|
|
181
|
+
# session.to_hash
|
|
182
|
+
# # => {"session_id"=>"e29b9ea315edf98aad94cc78c34cc9b2", "foo" => "bar"}
|
|
180
183
|
def update(hash)
|
|
181
184
|
unless hash.respond_to?(:to_hash)
|
|
182
185
|
raise TypeError, "no implicit conversion of #{hash.class.name} into Hash"
|
|
@@ -193,20 +196,20 @@ module ActionDispatch
|
|
|
193
196
|
@delegate.delete key.to_s
|
|
194
197
|
end
|
|
195
198
|
|
|
196
|
-
# Returns value of the given key from the session, or raises
|
|
197
|
-
#
|
|
198
|
-
#
|
|
199
|
+
# Returns value of the given key from the session, or raises `KeyError` if can't
|
|
200
|
+
# find the given key and no default value is set. Returns default value if
|
|
201
|
+
# specified.
|
|
199
202
|
#
|
|
200
|
-
#
|
|
201
|
-
#
|
|
203
|
+
# session.fetch(:foo)
|
|
204
|
+
# # => KeyError: key not found: "foo"
|
|
202
205
|
#
|
|
203
|
-
#
|
|
204
|
-
#
|
|
206
|
+
# session.fetch(:foo, :bar)
|
|
207
|
+
# # => :bar
|
|
205
208
|
#
|
|
206
|
-
#
|
|
207
|
-
#
|
|
208
|
-
#
|
|
209
|
-
#
|
|
209
|
+
# session.fetch(:foo) do
|
|
210
|
+
# :bar
|
|
211
|
+
# end
|
|
212
|
+
# # => :bar
|
|
210
213
|
def fetch(key, default = Unspecified, &block)
|
|
211
214
|
load_for_read!
|
|
212
215
|
if default == Unspecified
|