actionpack 6.1.4.1 → 7.0.0.rc2
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 +191 -378
- data/MIT-LICENSE +1 -1
- data/README.rdoc +2 -3
- data/lib/abstract_controller/asset_paths.rb +1 -1
- data/lib/abstract_controller/base.rb +7 -21
- data/lib/abstract_controller/caching/fragments.rb +2 -2
- data/lib/abstract_controller/caching.rb +1 -1
- data/lib/abstract_controller/callbacks.rb +21 -7
- data/lib/abstract_controller/collector.rb +4 -2
- data/lib/abstract_controller/error.rb +1 -1
- data/lib/abstract_controller/helpers.rb +3 -2
- data/lib/abstract_controller/logger.rb +1 -1
- data/lib/abstract_controller/railties/routes_helpers.rb +2 -0
- data/lib/abstract_controller/translation.rb +3 -2
- data/lib/abstract_controller/url_for.rb +4 -6
- data/lib/action_controller/api.rb +1 -1
- data/lib/action_controller/log_subscriber.rb +4 -3
- data/lib/action_controller/metal/conditional_get.rb +38 -1
- data/lib/action_controller/metal/content_security_policy.rb +1 -1
- data/lib/action_controller/metal/cookies.rb +1 -1
- data/lib/action_controller/metal/data_streaming.rb +5 -13
- data/lib/action_controller/metal/exceptions.rb +19 -30
- data/lib/action_controller/metal/flash.rb +6 -2
- data/lib/action_controller/metal/helpers.rb +1 -1
- data/lib/action_controller/metal/http_authentication.rb +17 -16
- data/lib/action_controller/metal/instrumentation.rb +57 -52
- data/lib/action_controller/metal/live.rb +42 -2
- data/lib/action_controller/metal/mime_responds.rb +3 -3
- data/lib/action_controller/metal/params_wrapper.rb +20 -11
- data/lib/action_controller/metal/permissions_policy.rb +1 -1
- data/lib/action_controller/metal/redirecting.rb +86 -16
- data/lib/action_controller/metal/rendering.rb +7 -7
- data/lib/action_controller/metal/request_forgery_protection.rb +64 -24
- data/lib/action_controller/metal/rescue.rb +1 -1
- data/lib/action_controller/metal/streaming.rb +1 -3
- data/lib/action_controller/metal/strong_parameters.rb +84 -47
- data/lib/action_controller/metal/testing.rb +0 -2
- data/lib/action_controller/metal.rb +7 -10
- data/lib/action_controller/railtie.rb +49 -6
- data/lib/action_controller/test_case.rb +19 -4
- data/lib/action_controller.rb +1 -5
- data/lib/action_dispatch/http/cache.rb +13 -6
- data/lib/action_dispatch/http/content_security_policy.rb +39 -35
- data/lib/action_dispatch/http/filter_parameters.rb +5 -0
- data/lib/action_dispatch/http/mime_negotiation.rb +13 -3
- data/lib/action_dispatch/http/mime_type.rb +9 -11
- data/lib/action_dispatch/http/parameters.rb +4 -4
- data/lib/action_dispatch/http/permissions_policy.rb +1 -1
- data/lib/action_dispatch/http/request.rb +10 -19
- data/lib/action_dispatch/http/response.rb +1 -13
- data/lib/action_dispatch/http/url.rb +11 -19
- data/lib/action_dispatch/journey/gtg/builder.rb +11 -12
- data/lib/action_dispatch/journey/gtg/simulator.rb +10 -4
- data/lib/action_dispatch/journey/gtg/transition_table.rb +77 -21
- data/lib/action_dispatch/journey/nodes/node.rb +70 -5
- data/lib/action_dispatch/journey/path/pattern.rb +22 -13
- data/lib/action_dispatch/journey/route.rb +6 -13
- data/lib/action_dispatch/journey/router/utils.rb +2 -2
- data/lib/action_dispatch/journey/router.rb +1 -1
- data/lib/action_dispatch/journey/routes.rb +3 -3
- 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/middleware/actionable_exceptions.rb +0 -1
- data/lib/action_dispatch/middleware/cookies.rb +8 -4
- data/lib/action_dispatch/middleware/debug_exceptions.rb +6 -4
- data/lib/action_dispatch/middleware/debug_locks.rb +3 -3
- data/lib/action_dispatch/middleware/exception_wrapper.rb +4 -0
- data/lib/action_dispatch/middleware/executor.rb +3 -0
- data/lib/action_dispatch/middleware/flash.rb +9 -11
- data/lib/action_dispatch/middleware/host_authorization.rb +44 -30
- data/lib/action_dispatch/middleware/remote_ip.rb +16 -4
- data/lib/action_dispatch/middleware/server_timing.rb +33 -0
- data/lib/action_dispatch/middleware/session/abstract_store.rb +1 -1
- data/lib/action_dispatch/middleware/show_exceptions.rb +17 -9
- data/lib/action_dispatch/middleware/stack.rb +27 -9
- data/lib/action_dispatch/middleware/static.rb +2 -6
- data/lib/action_dispatch/middleware/templates/rescues/_message_and_suggestions.html.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +4 -11
- data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +2 -2
- data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +4 -3
- data/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb +3 -1
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +4 -4
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +3 -3
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +28 -18
- data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +3 -3
- data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +3 -3
- data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +3 -3
- data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +3 -3
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +3 -3
- data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +5 -14
- data/lib/action_dispatch/railtie.rb +8 -2
- data/lib/action_dispatch/request/session.rb +43 -13
- data/lib/action_dispatch/routing/inspector.rb +1 -1
- data/lib/action_dispatch/routing/mapper.rb +54 -78
- data/lib/action_dispatch/routing/redirection.rb +0 -2
- data/lib/action_dispatch/routing/route_set.rb +14 -6
- data/lib/action_dispatch/routing/routes_proxy.rb +1 -1
- data/lib/action_dispatch/routing/url_for.rb +1 -2
- data/lib/action_dispatch/routing.rb +2 -2
- data/lib/action_dispatch/system_test_case.rb +12 -6
- data/lib/action_dispatch/system_testing/browser.rb +2 -12
- data/lib/action_dispatch/system_testing/driver.rb +35 -11
- data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +10 -6
- data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +0 -8
- data/lib/action_dispatch/testing/assertions.rb +2 -5
- data/lib/action_dispatch/testing/integration.rb +6 -8
- data/lib/action_dispatch/testing/test_process.rb +3 -26
- data/lib/action_dispatch.rb +2 -1
- data/lib/action_pack/gem_version.rb +4 -4
- data/lib/action_pack.rb +1 -1
- metadata +18 -16
@@ -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
|
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "action_dispatch/http/request"
|
4
|
-
|
5
3
|
module ActionDispatch
|
6
4
|
# This middleware guards from DNS rebinding attacks by explicitly permitting
|
7
5
|
# the hosts a request can be sent to, and is passed the options set in
|
@@ -13,7 +11,10 @@ module ActionDispatch
|
|
13
11
|
#
|
14
12
|
# When a request comes to an unauthorized host, the +response_app+
|
15
13
|
# application will be executed and rendered. If no +response_app+ is given, a
|
16
|
-
# default one will run
|
14
|
+
# default one will run.
|
15
|
+
# The default response app logs blocked host info with level 'error' and
|
16
|
+
# responds with <tt>403 Forbidden</tt>. The body of the response contains debug info
|
17
|
+
# if +config.consider_all_requests_local+ is set to true, otherwise the body is empty.
|
17
18
|
class HostAuthorization
|
18
19
|
class Permissions # :nodoc:
|
19
20
|
def initialize(hosts)
|
@@ -51,41 +52,58 @@ module ActionDispatch
|
|
51
52
|
|
52
53
|
def sanitize_string(host)
|
53
54
|
if host.start_with?(".")
|
54
|
-
/\A(
|
55
|
+
/\A([a-z0-9-]+\.)?#{Regexp.escape(host[1..-1])}\z/i
|
55
56
|
else
|
56
57
|
/\A#{Regexp.escape host}\z/i
|
57
58
|
end
|
58
59
|
end
|
59
60
|
end
|
60
61
|
|
61
|
-
|
62
|
-
|
62
|
+
class DefaultResponseApp # :nodoc:
|
63
|
+
RESPONSE_STATUS = 403
|
64
|
+
|
65
|
+
def call(env)
|
66
|
+
request = Request.new(env)
|
67
|
+
format = request.xhr? ? "text/plain" : "text/html"
|
68
|
+
|
69
|
+
log_error(request)
|
70
|
+
response(format, response_body(request))
|
71
|
+
end
|
63
72
|
|
64
|
-
|
65
|
-
|
66
|
-
|
73
|
+
private
|
74
|
+
def response_body(request)
|
75
|
+
return "" unless request.get_header("action_dispatch.show_detailed_exceptions")
|
76
|
+
|
77
|
+
template = DebugView.new(host: request.host)
|
78
|
+
template.render(template: "rescues/blocked_host", layout: "rescues/layout")
|
79
|
+
end
|
80
|
+
|
81
|
+
def response(format, body)
|
82
|
+
[RESPONSE_STATUS,
|
83
|
+
{ "Content-Type" => "#{format}; charset=#{Response.default_charset}",
|
84
|
+
"Content-Length" => body.bytesize.to_s },
|
85
|
+
[body]]
|
86
|
+
end
|
67
87
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
88
|
+
def log_error(request)
|
89
|
+
logger = available_logger(request)
|
90
|
+
|
91
|
+
return unless logger
|
92
|
+
|
93
|
+
logger.error("[#{self.class.name}] Blocked host: #{request.host}")
|
94
|
+
end
|
95
|
+
|
96
|
+
def available_logger(request)
|
97
|
+
request.logger || ActionView::Base.logger
|
98
|
+
end
|
72
99
|
end
|
73
100
|
|
74
|
-
def initialize(app, hosts,
|
101
|
+
def initialize(app, hosts, exclude: nil, response_app: nil)
|
75
102
|
@app = app
|
76
103
|
@permissions = Permissions.new(hosts)
|
77
104
|
@exclude = exclude
|
78
105
|
|
79
|
-
|
80
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
81
|
-
`action_dispatch.hosts_response_app` is deprecated and will be ignored in Rails 6.2.
|
82
|
-
Use the Host Authorization `response_app` setting instead.
|
83
|
-
MSG
|
84
|
-
|
85
|
-
response_app ||= deprecated_response_app
|
86
|
-
end
|
87
|
-
|
88
|
-
@response_app = response_app || DEFAULT_RESPONSE_APP
|
106
|
+
@response_app = response_app || DefaultResponseApp.new
|
89
107
|
end
|
90
108
|
|
91
109
|
def call(env)
|
@@ -102,13 +120,9 @@ module ActionDispatch
|
|
102
120
|
end
|
103
121
|
|
104
122
|
private
|
105
|
-
HOSTNAME = /[a-z0-9.-]+|\[[a-f0-9]*:[a-f0-9.:]+\]/i
|
106
|
-
VALID_ORIGIN_HOST = /\A(#{HOSTNAME})(?::\d+)?\z/
|
107
|
-
VALID_FORWARDED_HOST = /(?:\A|,[ ]?)(#{HOSTNAME})(?::\d+)?\z/
|
108
|
-
|
109
123
|
def authorized?(request)
|
110
|
-
origin_host = request.get_header("HTTP_HOST")
|
111
|
-
forwarded_host = request.x_forwarded_host&.
|
124
|
+
origin_host = request.get_header("HTTP_HOST")
|
125
|
+
forwarded_host = request.x_forwarded_host&.split(/,\s?/)&.last
|
112
126
|
|
113
127
|
@permissions.allows?(origin_host) && (forwarded_host.blank? || @permissions.allows?(forwarded_host))
|
114
128
|
end
|
@@ -51,10 +51,8 @@ module ActionDispatch
|
|
51
51
|
# clients (like WAP devices), or behind proxies that set headers in an
|
52
52
|
# incorrect or confusing way (like AWS ELB).
|
53
53
|
#
|
54
|
-
# The +custom_proxies+ argument can take an
|
55
|
-
#
|
56
|
-
# single string, IPAddr, or Regexp object is provided, it will be used in
|
57
|
-
# addition to +TRUSTED_PROXIES+. Any proxy setup will put the value you
|
54
|
+
# The +custom_proxies+ argument can take an enumerable which will be used
|
55
|
+
# instead of +TRUSTED_PROXIES+. Any proxy setup will put the value you
|
58
56
|
# want in the middle (or at the beginning) of the X-Forwarded-For list,
|
59
57
|
# with your proxy servers after it. If your proxies aren't removed, pass
|
60
58
|
# them in via the +custom_proxies+ parameter. That way, the middleware will
|
@@ -67,6 +65,20 @@ module ActionDispatch
|
|
67
65
|
elsif custom_proxies.respond_to?(:any?)
|
68
66
|
custom_proxies
|
69
67
|
else
|
68
|
+
ActiveSupport::Deprecation.warn(<<~EOM)
|
69
|
+
Setting config.action_dispatch.trusted_proxies to a single value has
|
70
|
+
been deprecated. Please set this to an enumerable instead. For
|
71
|
+
example, instead of:
|
72
|
+
|
73
|
+
config.action_dispatch.trusted_proxies = IPAddr.new("10.0.0.0/8")
|
74
|
+
|
75
|
+
Wrap the value in an Array:
|
76
|
+
|
77
|
+
config.action_dispatch.trusted_proxies = [IPAddr.new("10.0.0.0/8")]
|
78
|
+
|
79
|
+
Note that unlike passing a single argument, passing an enumerable
|
80
|
+
will *replace* the default set of trusted proxies.
|
81
|
+
EOM
|
70
82
|
Array(custom_proxies) + TRUSTED_PROXIES
|
71
83
|
end
|
72
84
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/notifications"
|
4
|
+
|
5
|
+
module ActionDispatch
|
6
|
+
class ServerTiming
|
7
|
+
SERVER_TIMING_HEADER = "Server-Timing"
|
8
|
+
|
9
|
+
def initialize(app)
|
10
|
+
@app = app
|
11
|
+
end
|
12
|
+
|
13
|
+
def call(env)
|
14
|
+
events = []
|
15
|
+
subscriber = ActiveSupport::Notifications.subscribe(/.*/) do |*args|
|
16
|
+
events << ActiveSupport::Notifications::Event.new(*args)
|
17
|
+
end
|
18
|
+
|
19
|
+
status, headers, body = begin
|
20
|
+
@app.call(env)
|
21
|
+
ensure
|
22
|
+
ActiveSupport::Notifications.unsubscribe(subscriber)
|
23
|
+
end
|
24
|
+
|
25
|
+
header_info = events.group_by(&:name).map do |event_name, events_collection|
|
26
|
+
"#{event_name};dur=#{events_collection.sum(&:duration)}"
|
27
|
+
end
|
28
|
+
headers[SERVER_TIMING_HEADER] = header_info.join(", ")
|
29
|
+
|
30
|
+
[ status, headers, body ]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -8,7 +8,7 @@ require "action_dispatch/request/session"
|
|
8
8
|
|
9
9
|
module ActionDispatch
|
10
10
|
module Session
|
11
|
-
class SessionRestoreError < StandardError
|
11
|
+
class SessionRestoreError < StandardError # :nodoc:
|
12
12
|
def initialize
|
13
13
|
super("Session contains objects whose class definition isn't available.\n" \
|
14
14
|
"Remember to require the classes for all objects kept in the session.\n" \
|
@@ -1,6 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "action_dispatch/http/request"
|
4
3
|
require "action_dispatch/middleware/exception_wrapper"
|
5
4
|
|
6
5
|
module ActionDispatch
|
@@ -15,14 +14,8 @@ module ActionDispatch
|
|
15
14
|
# If the application returns a "X-Cascade" pass response, this middleware
|
16
15
|
# will send an empty response as result with the correct status code.
|
17
16
|
# If any exception happens inside the exceptions app, this middleware
|
18
|
-
# catches the exceptions and returns a
|
17
|
+
# catches the exceptions and returns a failsafe response.
|
19
18
|
class ShowExceptions
|
20
|
-
FAILSAFE_RESPONSE = [500, { "Content-Type" => "text/plain" },
|
21
|
-
["500 Internal Server Error\n" \
|
22
|
-
"If you are the administrator of this website, then please read this web " \
|
23
|
-
"application's log file and/or the web server's log file to find out what " \
|
24
|
-
"went wrong."]]
|
25
|
-
|
26
19
|
def initialize(app, exceptions_app)
|
27
20
|
@app = app
|
28
21
|
@exceptions_app = exceptions_app
|
@@ -47,13 +40,28 @@ module ActionDispatch
|
|
47
40
|
request.set_header "action_dispatch.exception", wrapper.unwrapped_exception
|
48
41
|
request.set_header "action_dispatch.original_path", request.path_info
|
49
42
|
request.set_header "action_dispatch.original_request_method", request.raw_request_method
|
43
|
+
fallback_to_html_format_if_invalid_mime_type(request)
|
50
44
|
request.path_info = "/#{status}"
|
51
45
|
request.request_method = "GET"
|
52
46
|
response = @exceptions_app.call(request.env)
|
53
47
|
response[1]["X-Cascade"] == "pass" ? pass_response(status) : response
|
54
48
|
rescue Exception => failsafe_error
|
55
49
|
$stderr.puts "Error during failsafe response: #{failsafe_error}\n #{failsafe_error.backtrace * "\n "}"
|
56
|
-
|
50
|
+
|
51
|
+
[500, { "Content-Type" => "text/plain" },
|
52
|
+
["500 Internal Server Error\n" \
|
53
|
+
"If you are the administrator of this website, then please read this web " \
|
54
|
+
"application's log file and/or the web server's log file to find out what " \
|
55
|
+
"went wrong."]]
|
56
|
+
end
|
57
|
+
|
58
|
+
def fallback_to_html_format_if_invalid_mime_type(request)
|
59
|
+
# If the MIME type for the request is invalid then the
|
60
|
+
# @exceptions_app may not be able to handle it. To make it
|
61
|
+
# easier to handle, we switch to HTML.
|
62
|
+
request.formats
|
63
|
+
rescue ActionDispatch::Http::MimeNegotiation::InvalidType
|
64
|
+
request.set_header "HTTP_ACCEPT", "text/html"
|
57
65
|
end
|
58
66
|
|
59
67
|
def pass_response(status)
|
@@ -72,8 +72,8 @@ module ActionDispatch
|
|
72
72
|
yield(self) if block_given?
|
73
73
|
end
|
74
74
|
|
75
|
-
def each
|
76
|
-
@middlewares.each
|
75
|
+
def each(&block)
|
76
|
+
@middlewares.each(&block)
|
77
77
|
end
|
78
78
|
|
79
79
|
def size
|
@@ -91,7 +91,7 @@ module ActionDispatch
|
|
91
91
|
def unshift(klass, *args, &block)
|
92
92
|
middlewares.unshift(build_middleware(klass, args, block))
|
93
93
|
end
|
94
|
-
ruby2_keywords(:unshift)
|
94
|
+
ruby2_keywords(:unshift)
|
95
95
|
|
96
96
|
def initialize_copy(other)
|
97
97
|
self.middlewares = other.middlewares.dup
|
@@ -101,7 +101,7 @@ module ActionDispatch
|
|
101
101
|
index = assert_index(index, :before)
|
102
102
|
middlewares.insert(index, build_middleware(klass, args, block))
|
103
103
|
end
|
104
|
-
ruby2_keywords(:insert)
|
104
|
+
ruby2_keywords(:insert)
|
105
105
|
|
106
106
|
alias_method :insert_before, :insert
|
107
107
|
|
@@ -109,17 +109,29 @@ module ActionDispatch
|
|
109
109
|
index = assert_index(index, :after)
|
110
110
|
insert(index + 1, *args, &block)
|
111
111
|
end
|
112
|
-
ruby2_keywords(:insert_after)
|
112
|
+
ruby2_keywords(:insert_after)
|
113
113
|
|
114
114
|
def swap(target, *args, &block)
|
115
115
|
index = assert_index(target, :before)
|
116
116
|
insert(index, *args, &block)
|
117
117
|
middlewares.delete_at(index + 1)
|
118
118
|
end
|
119
|
-
ruby2_keywords(:swap)
|
119
|
+
ruby2_keywords(:swap)
|
120
120
|
|
121
|
+
# Deletes a middleware from the middleware stack.
|
122
|
+
#
|
123
|
+
# Returns the array of middlewares not including the deleted item, or
|
124
|
+
# returns nil if the target is not found.
|
121
125
|
def delete(target)
|
122
|
-
middlewares.
|
126
|
+
middlewares.reject! { |m| m.name == target.name }
|
127
|
+
end
|
128
|
+
|
129
|
+
# Deletes a middleware from the middleware stack.
|
130
|
+
#
|
131
|
+
# Returns the array of middlewares not including the deleted item, or
|
132
|
+
# raises +RuntimeError+ if the target is not found.
|
133
|
+
def delete!(target)
|
134
|
+
delete(target) || (raise "No such middleware to remove: #{target.inspect}")
|
123
135
|
end
|
124
136
|
|
125
137
|
def move(target, source)
|
@@ -143,7 +155,7 @@ module ActionDispatch
|
|
143
155
|
def use(klass, *args, &block)
|
144
156
|
middlewares.push(build_middleware(klass, args, block))
|
145
157
|
end
|
146
|
-
ruby2_keywords(:use)
|
158
|
+
ruby2_keywords(:use)
|
147
159
|
|
148
160
|
def build(app = nil, &block)
|
149
161
|
instrumenting = ActiveSupport::Notifications.notifier.listening?(InstrumentationProxy::EVENT_NAME)
|
@@ -158,7 +170,7 @@ module ActionDispatch
|
|
158
170
|
|
159
171
|
private
|
160
172
|
def assert_index(index, where)
|
161
|
-
i = index.is_a?(Integer) ? index :
|
173
|
+
i = index.is_a?(Integer) ? index : index_of(index)
|
162
174
|
raise "No such middleware to insert #{where}: #{index.inspect}" unless i
|
163
175
|
i
|
164
176
|
end
|
@@ -166,5 +178,11 @@ module ActionDispatch
|
|
166
178
|
def build_middleware(klass, args, block)
|
167
179
|
Middleware.new(klass, args, block)
|
168
180
|
end
|
181
|
+
|
182
|
+
def index_of(klass)
|
183
|
+
middlewares.index do |m|
|
184
|
+
m.name == klass.name
|
185
|
+
end
|
186
|
+
end
|
169
187
|
end
|
170
188
|
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "rack/utils"
|
4
|
-
require "active_support/core_ext/uri"
|
5
4
|
|
6
5
|
module ActionDispatch
|
7
6
|
# This middleware serves static files from disk, if available.
|
@@ -137,11 +136,8 @@ module ActionDispatch
|
|
137
136
|
end
|
138
137
|
|
139
138
|
def file_readable?(path)
|
140
|
-
|
141
|
-
|
142
|
-
false
|
143
|
-
else
|
144
|
-
file_stat.file? && file_stat.readable?
|
139
|
+
file_path = File.join(@root, path.b)
|
140
|
+
File.file?(file_path) && File.readable?(file_path)
|
145
141
|
end
|
146
142
|
|
147
143
|
def compressible?(content_type)
|
@@ -1,24 +1,17 @@
|
|
1
|
-
|
2
|
-
<% if (hide = @exception.blamed_files.length > 8) %>
|
3
|
-
<a href="#" onclick="return toggleTrace()">Toggle blamed files</a>
|
4
|
-
<% end %>
|
5
|
-
<pre id="blame_trace" <%='style="display:none"' if hide %>><code><%= @exception.describe_blame %></code></pre>
|
6
|
-
<% end %>
|
7
|
-
|
8
|
-
<h2 style="margin-top: 30px">Request</h2>
|
1
|
+
<h2 class="request-heading">Request</h2>
|
9
2
|
<% if params_valid? %>
|
10
3
|
<p><b>Parameters</b>:</p> <pre><%= debug_params(@request.filtered_parameters) %></pre>
|
11
4
|
<% end %>
|
12
5
|
|
13
6
|
<div class="details">
|
14
7
|
<div class="summary"><a href="#" onclick="return toggleSessionDump()">Toggle session dump</a></div>
|
15
|
-
<div id="session_dump"
|
8
|
+
<div id="session_dump" class="hidden"><pre><%= debug_hash @request.session %></pre></div>
|
16
9
|
</div>
|
17
10
|
|
18
11
|
<div class="details">
|
19
12
|
<div class="summary"><a href="#" onclick="return toggleEnvDump()">Toggle env dump</a></div>
|
20
|
-
<div id="env_dump"
|
13
|
+
<div id="env_dump" class="hidden"><pre><%= debug_hash @request.env.slice(*@request.class::ENV_METHODS) %></pre></div>
|
21
14
|
</div>
|
22
15
|
|
23
|
-
<h2
|
16
|
+
<h2 class="response-heading">Response</h2>
|
24
17
|
<p><b>Headers</b>:</p> <pre><%= debug_headers(defined?(@response) ? @response.headers : {}) %></pre>
|
@@ -14,7 +14,7 @@
|
|
14
14
|
|
15
15
|
<% traces.each do |name, trace| %>
|
16
16
|
<div id="<%= "#{name.gsub(/\s/, '-')}-#{error_index}" %>" style="display: <%= (name == trace_to_show) ? 'block' : 'none' %>;">
|
17
|
-
<code
|
17
|
+
<code class="traces">
|
18
18
|
<% trace.each do |frame| %>
|
19
19
|
<a class="trace-frames trace-frames-<%= error_index %>" data-exception-object-id="<%= frame[:exception_object_id] %>" data-frame-id="<%= frame[:id] %>" href="#">
|
20
20
|
<%= frame[:trace] %>
|
@@ -25,7 +25,7 @@
|
|
25
25
|
</div>
|
26
26
|
<% end %>
|
27
27
|
|
28
|
-
<script
|
28
|
+
<script>
|
29
29
|
(function() {
|
30
30
|
var traceFrames = document.getElementsByClassName('trace-frames-<%= error_index %>');
|
31
31
|
var selectedFrame, currentSource = document.getElementById('frame-source-<%= error_index %>-0');
|
@@ -1,7 +1,8 @@
|
|
1
1
|
<header>
|
2
2
|
<h1>Blocked host: <%= @host %></h1>
|
3
3
|
</header>
|
4
|
-
<
|
5
|
-
<h2>To allow requests to <%= @host
|
4
|
+
<main role="main" id="container">
|
5
|
+
<h2>To allow requests to <%= @host %> make sure it is a valid hostname (containing only numbers, letters, dashes and dots), then add the following to your environment configuration:</h2>
|
6
6
|
<pre>config.hosts << "<%= @host %>"</pre>
|
7
|
-
</
|
7
|
+
<p>For more details view: <a href="https://guides.rubyonrails.org/configuring.html#actiondispatch-hostauthorization">the Host Authorization guide</a></p>
|
8
|
+
</main>
|
@@ -1,5 +1,7 @@
|
|
1
1
|
Blocked host: <%= @host %>
|
2
2
|
|
3
|
-
To allow requests to <%= @host
|
3
|
+
To allow requests to <%= @host %> make sure it is a valid hostname (containing only numbers, letters, dashes and dots), then add the following to your environment configuration:
|
4
4
|
|
5
5
|
config.hosts << "<%= @host %>"
|
6
|
+
|
7
|
+
For more details on host authorization view: https://guides.rubyonrails.org/configuring.html#actiondispatch-hostauthorization
|
@@ -7,7 +7,7 @@
|
|
7
7
|
</h1>
|
8
8
|
</header>
|
9
9
|
|
10
|
-
<
|
10
|
+
<main role="main" id="container">
|
11
11
|
<%= render "rescues/message_and_suggestions", exception: @exception %>
|
12
12
|
<%= render "rescues/actions", exception: @exception, request: @request %>
|
13
13
|
|
@@ -20,16 +20,16 @@
|
|
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="#"
|
23
|
+
<a class="summary" href="#" onclick="return toggle(<%= wrapper.exception.object_id %>)">
|
24
24
|
<%= wrapper.exception.class.name %>: <%= h wrapper.exception.message %>
|
25
25
|
</a>
|
26
26
|
</div>
|
27
27
|
|
28
|
-
<div id="<%= wrapper.exception.object_id %>"
|
28
|
+
<div id="<%= wrapper.exception.object_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>
|
32
32
|
<% end %>
|
33
33
|
|
34
34
|
<%= render template: "rescues/_request_and_response" %>
|
35
|
-
</
|
35
|
+
</main>
|
@@ -1,4 +1,4 @@
|
|
1
|
-
<header>
|
1
|
+
<header role="banner">
|
2
2
|
<h1>
|
3
3
|
<%= @exception.class.to_s %>
|
4
4
|
<% if @request.parameters['controller'] %>
|
@@ -7,7 +7,7 @@
|
|
7
7
|
</h1>
|
8
8
|
</header>
|
9
9
|
|
10
|
-
<
|
10
|
+
<main role="main" id="container">
|
11
11
|
<h2>
|
12
12
|
<%= h @exception.message %>
|
13
13
|
<% if defined?(ActiveStorage) && @exception.message.match?(%r{#{ActiveStorage::Blob.table_name}|#{ActiveStorage::Attachment.table_name}}) %>
|
@@ -21,4 +21,4 @@
|
|
21
21
|
<%= render "rescues/source", source_extracts: @source_extracts, show_source_idx: @show_source_idx %>
|
22
22
|
<%= render "rescues/trace", traces: @traces, trace_to_show: @trace_to_show %>
|
23
23
|
<%= render template: "rescues/_request_and_response" %>
|
24
|
-
</
|
24
|
+
</main>
|