actionpack 5.1.7 → 5.2.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of actionpack might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/CHANGELOG.md +132 -490
- data/README.rdoc +1 -1
- data/lib/abstract_controller.rb +2 -0
- data/lib/abstract_controller/asset_paths.rb +2 -0
- data/lib/abstract_controller/base.rb +10 -2
- data/lib/abstract_controller/caching.rb +3 -2
- data/lib/abstract_controller/caching/fragments.rb +30 -7
- data/lib/abstract_controller/callbacks.rb +25 -3
- data/lib/abstract_controller/collector.rb +2 -0
- data/lib/abstract_controller/error.rb +2 -0
- data/lib/abstract_controller/helpers.rb +4 -5
- data/lib/abstract_controller/logger.rb +2 -0
- data/lib/abstract_controller/railties/routes_helpers.rb +2 -0
- data/lib/abstract_controller/rendering.rb +9 -16
- data/lib/abstract_controller/translation.rb +2 -0
- data/lib/abstract_controller/url_for.rb +2 -0
- data/lib/action_controller.rb +3 -0
- data/lib/action_controller/api.rb +2 -0
- data/lib/action_controller/api/api_rendering.rb +2 -0
- data/lib/action_controller/base.rb +3 -0
- data/lib/action_controller/caching.rb +2 -0
- data/lib/action_controller/form_builder.rb +2 -0
- data/lib/action_controller/log_subscriber.rb +5 -3
- data/lib/action_controller/metal.rb +3 -2
- data/lib/action_controller/metal/basic_implicit_render.rb +2 -0
- data/lib/action_controller/metal/conditional_get.rb +4 -3
- data/lib/action_controller/metal/content_security_policy.rb +26 -0
- data/lib/action_controller/metal/cookies.rb +2 -0
- data/lib/action_controller/metal/data_streaming.rb +7 -5
- data/lib/action_controller/metal/etag_with_flash.rb +2 -0
- data/lib/action_controller/metal/etag_with_template_digest.rb +3 -2
- data/lib/action_controller/metal/exceptions.rb +2 -3
- data/lib/action_controller/metal/flash.rb +3 -2
- data/lib/action_controller/metal/force_ssl.rb +2 -0
- data/lib/action_controller/metal/head.rb +2 -0
- data/lib/action_controller/metal/helpers.rb +4 -3
- data/lib/action_controller/metal/http_authentication.rb +8 -9
- data/lib/action_controller/metal/implicit_render.rb +2 -0
- data/lib/action_controller/metal/instrumentation.rb +4 -6
- data/lib/action_controller/metal/live.rb +3 -1
- data/lib/action_controller/metal/mime_responds.rb +3 -1
- data/lib/action_controller/metal/parameter_encoding.rb +2 -0
- data/lib/action_controller/metal/params_wrapper.rb +13 -9
- data/lib/action_controller/metal/redirecting.rb +21 -10
- data/lib/action_controller/metal/renderers.rb +4 -3
- data/lib/action_controller/metal/rendering.rb +2 -2
- data/lib/action_controller/metal/request_forgery_protection.rb +22 -6
- data/lib/action_controller/metal/rescue.rb +5 -3
- data/lib/action_controller/metal/streaming.rb +2 -0
- data/lib/action_controller/metal/strong_parameters.rb +19 -11
- data/lib/action_controller/metal/testing.rb +2 -6
- data/lib/action_controller/metal/url_for.rb +2 -0
- data/lib/action_controller/railtie.rb +16 -4
- data/lib/action_controller/railties/helpers.rb +2 -0
- data/lib/action_controller/renderer.rb +2 -0
- data/lib/action_controller/template_assertions.rb +2 -0
- data/lib/action_controller/test_case.rb +4 -1
- data/lib/action_dispatch.rb +3 -0
- data/lib/action_dispatch/http/cache.rb +15 -9
- data/lib/action_dispatch/http/content_security_policy.rb +233 -0
- data/lib/action_dispatch/http/filter_parameters.rb +4 -2
- data/lib/action_dispatch/http/filter_redirect.rb +2 -0
- data/lib/action_dispatch/http/headers.rb +2 -0
- data/lib/action_dispatch/http/mime_negotiation.rb +4 -13
- data/lib/action_dispatch/http/mime_type.rb +15 -13
- data/lib/action_dispatch/http/mime_types.rb +4 -2
- data/lib/action_dispatch/http/parameter_filter.rb +2 -0
- data/lib/action_dispatch/http/parameters.rb +6 -9
- data/lib/action_dispatch/http/rack_cache.rb +2 -0
- data/lib/action_dispatch/http/request.rb +36 -16
- data/lib/action_dispatch/http/response.rb +11 -9
- data/lib/action_dispatch/http/upload.rb +2 -0
- data/lib/action_dispatch/http/url.rb +4 -5
- data/lib/action_dispatch/journey.rb +2 -0
- data/lib/action_dispatch/journey/formatter.rb +4 -2
- data/lib/action_dispatch/journey/gtg/builder.rb +2 -0
- data/lib/action_dispatch/journey/gtg/simulator.rb +2 -8
- data/lib/action_dispatch/journey/gtg/transition_table.rb +3 -2
- data/lib/action_dispatch/journey/nfa/builder.rb +2 -0
- data/lib/action_dispatch/journey/nfa/dot.rb +2 -0
- data/lib/action_dispatch/journey/nfa/simulator.rb +2 -0
- data/lib/action_dispatch/journey/nfa/transition_table.rb +2 -0
- data/lib/action_dispatch/journey/nodes/node.rb +2 -0
- data/lib/action_dispatch/journey/parser_extras.rb +2 -0
- data/lib/action_dispatch/journey/path/pattern.rb +2 -0
- data/lib/action_dispatch/journey/route.rb +15 -6
- data/lib/action_dispatch/journey/router.rb +3 -1
- data/lib/action_dispatch/journey/router/utils.rb +14 -7
- data/lib/action_dispatch/journey/routes.rb +2 -1
- data/lib/action_dispatch/journey/scanner.rb +1 -0
- data/lib/action_dispatch/journey/visitors.rb +5 -3
- data/lib/action_dispatch/middleware/callbacks.rb +2 -0
- data/lib/action_dispatch/middleware/cookies.rb +141 -91
- data/lib/action_dispatch/middleware/debug_exceptions.rb +4 -2
- data/lib/action_dispatch/middleware/debug_locks.rb +9 -7
- data/lib/action_dispatch/middleware/exception_wrapper.rb +4 -6
- data/lib/action_dispatch/middleware/executor.rb +2 -0
- data/lib/action_dispatch/middleware/flash.rb +3 -1
- data/lib/action_dispatch/middleware/public_exceptions.rb +6 -4
- data/lib/action_dispatch/middleware/reloader.rb +2 -0
- data/lib/action_dispatch/middleware/remote_ip.rb +7 -5
- data/lib/action_dispatch/middleware/request_id.rb +2 -0
- data/lib/action_dispatch/middleware/session/abstract_store.rb +3 -1
- data/lib/action_dispatch/middleware/session/cache_store.rb +2 -0
- data/lib/action_dispatch/middleware/session/cookie_store.rb +13 -25
- data/lib/action_dispatch/middleware/session/mem_cache_store.rb +2 -0
- data/lib/action_dispatch/middleware/show_exceptions.rb +3 -1
- data/lib/action_dispatch/middleware/ssl.rb +42 -37
- data/lib/action_dispatch/middleware/stack.rb +2 -0
- data/lib/action_dispatch/middleware/static.rb +10 -8
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +1 -0
- data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +6 -2
- data/lib/action_dispatch/railtie.rb +7 -0
- data/lib/action_dispatch/request/session.rb +8 -4
- data/lib/action_dispatch/request/utils.rb +4 -4
- data/lib/action_dispatch/routing.rb +3 -1
- data/lib/action_dispatch/routing/endpoint.rb +8 -4
- data/lib/action_dispatch/routing/inspector.rb +5 -3
- data/lib/action_dispatch/routing/mapper.rb +62 -51
- data/lib/action_dispatch/routing/polymorphic_routes.rb +2 -0
- data/lib/action_dispatch/routing/redirection.rb +7 -5
- data/lib/action_dispatch/routing/route_set.rb +26 -33
- data/lib/action_dispatch/routing/routes_proxy.rb +5 -2
- data/lib/action_dispatch/routing/url_for.rb +6 -4
- data/lib/action_dispatch/system_test_case.rb +14 -6
- data/lib/action_dispatch/system_testing/driver.rb +20 -2
- data/lib/action_dispatch/system_testing/server.rb +2 -16
- data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +6 -4
- data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +2 -0
- data/lib/action_dispatch/system_testing/test_helpers/undef_methods.rb +26 -0
- data/lib/action_dispatch/testing/assertion_response.rb +2 -0
- data/lib/action_dispatch/testing/assertions.rb +2 -0
- data/lib/action_dispatch/testing/assertions/response.rb +4 -2
- data/lib/action_dispatch/testing/assertions/routing.rb +5 -5
- data/lib/action_dispatch/testing/integration.rb +24 -21
- data/lib/action_dispatch/testing/request_encoder.rb +2 -0
- data/lib/action_dispatch/testing/test_process.rb +2 -0
- data/lib/action_dispatch/testing/test_request.rb +3 -1
- data/lib/action_dispatch/testing/test_response.rb +23 -3
- data/lib/action_pack.rb +2 -0
- data/lib/action_pack/gem_version.rb +5 -3
- data/lib/action_pack/version.rb +2 -0
- metadata +17 -13
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "action_dispatch/http/request"
|
2
4
|
require "action_dispatch/middleware/exception_wrapper"
|
3
5
|
require "action_dispatch/routing/inspector"
|
@@ -10,7 +12,7 @@ module ActionDispatch
|
|
10
12
|
# This middleware is responsible for logging exceptions and
|
11
13
|
# showing a debugging page in case the request is local.
|
12
14
|
class DebugExceptions
|
13
|
-
RESCUES_TEMPLATE_PATH = File.expand_path("
|
15
|
+
RESCUES_TEMPLATE_PATH = File.expand_path("templates", __dir__)
|
14
16
|
|
15
17
|
class DebugView < ActionView::Base
|
16
18
|
def debug_params(params)
|
@@ -21,7 +23,7 @@ module ActionDispatch
|
|
21
23
|
if clean_params.empty?
|
22
24
|
"None"
|
23
25
|
else
|
24
|
-
PP.pp(clean_params, "", 200)
|
26
|
+
PP.pp(clean_params, "".dup, 200)
|
25
27
|
end
|
26
28
|
end
|
27
29
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActionDispatch
|
2
4
|
# This middleware can be used to diagnose deadlocks in the autoload interlock.
|
3
5
|
#
|
@@ -41,7 +43,7 @@ module ActionDispatch
|
|
41
43
|
|
42
44
|
private
|
43
45
|
def render_details(req)
|
44
|
-
threads = ActiveSupport::Dependencies.interlock.raw_state do |
|
46
|
+
threads = ActiveSupport::Dependencies.interlock.raw_state do |raw_threads|
|
45
47
|
# The Interlock itself comes to a complete halt as long as this block
|
46
48
|
# is executing. That gives us a more consistent picture of everything,
|
47
49
|
# but creates a pretty strong Observer Effect.
|
@@ -51,29 +53,29 @@ module ActionDispatch
|
|
51
53
|
# strictly diagnostic tool (to be used when something has gone wrong),
|
52
54
|
# and not for any sort of general monitoring.
|
53
55
|
|
54
|
-
|
56
|
+
raw_threads.each.with_index do |(thread, info), idx|
|
55
57
|
info[:index] = idx
|
56
58
|
info[:backtrace] = thread.backtrace
|
57
59
|
end
|
58
60
|
|
59
|
-
|
61
|
+
raw_threads
|
60
62
|
end
|
61
63
|
|
62
64
|
str = threads.map do |thread, info|
|
63
65
|
if info[:exclusive]
|
64
|
-
lock_state = "Exclusive"
|
66
|
+
lock_state = "Exclusive".dup
|
65
67
|
elsif info[:sharing] > 0
|
66
|
-
lock_state = "Sharing"
|
68
|
+
lock_state = "Sharing".dup
|
67
69
|
lock_state << " x#{info[:sharing]}" if info[:sharing] > 1
|
68
70
|
else
|
69
|
-
lock_state = "No lock"
|
71
|
+
lock_state = "No lock".dup
|
70
72
|
end
|
71
73
|
|
72
74
|
if info[:waiting]
|
73
75
|
lock_state << " (yielded share)"
|
74
76
|
end
|
75
77
|
|
76
|
-
msg = "Thread #{info[:index]} [0x#{thread.__id__.to_s(16)} #{thread.status || 'dead'}] #{lock_state}\n"
|
78
|
+
msg = "Thread #{info[:index]} [0x#{thread.__id__.to_s(16)} #{thread.status || 'dead'}] #{lock_state}\n".dup
|
77
79
|
|
78
80
|
if info[:sleeper]
|
79
81
|
msg << " Waiting in #{info[:sleeper]}"
|
@@ -1,11 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "active_support/core_ext/module/attribute_accessors"
|
2
4
|
require "rack/utils"
|
3
5
|
|
4
6
|
module ActionDispatch
|
5
7
|
class ExceptionWrapper
|
6
|
-
cattr_accessor :rescue_responses
|
7
|
-
@@rescue_responses = Hash.new(:internal_server_error)
|
8
|
-
@@rescue_responses.merge!(
|
8
|
+
cattr_accessor :rescue_responses, default: Hash.new(:internal_server_error).merge!(
|
9
9
|
"ActionController::RoutingError" => :not_found,
|
10
10
|
"AbstractController::ActionNotFound" => :not_found,
|
11
11
|
"ActionController::MethodNotAllowed" => :method_not_allowed,
|
@@ -21,9 +21,7 @@ module ActionDispatch
|
|
21
21
|
"Rack::QueryParser::InvalidParameterError" => :bad_request
|
22
22
|
)
|
23
23
|
|
24
|
-
cattr_accessor :rescue_templates
|
25
|
-
@@rescue_templates = Hash.new("diagnostics")
|
26
|
-
@@rescue_templates.merge!(
|
24
|
+
cattr_accessor :rescue_templates, default: Hash.new("diagnostics").merge!(
|
27
25
|
"ActionView::MissingTemplate" => "missing_template",
|
28
26
|
"ActionController::RoutingError" => "routing_error",
|
29
27
|
"AbstractController::ActionNotFound" => "unknown_action",
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "active_support/core_ext/hash/keys"
|
2
4
|
|
3
5
|
module ActionDispatch
|
@@ -65,7 +67,7 @@ module ActionDispatch
|
|
65
67
|
self.flash = flash_hash.dup
|
66
68
|
end
|
67
69
|
|
68
|
-
if (!session.respond_to?(:loaded?) || session.loaded?) && #
|
70
|
+
if (!session.respond_to?(:loaded?) || session.loaded?) && # reset_session uses {}, which doesn't implement #loaded?
|
69
71
|
session.key?("flash") && session["flash"].nil?
|
70
72
|
session.delete("flash")
|
71
73
|
end
|
@@ -1,11 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActionDispatch
|
2
4
|
# When called, this middleware renders an error page. By default if an HTML
|
3
|
-
# response is expected it will render static error pages from the
|
5
|
+
# response is expected it will render static error pages from the <tt>/public</tt>
|
4
6
|
# directory. For example when this middleware receives a 500 response it will
|
5
|
-
# render the template found in
|
7
|
+
# render the template found in <tt>/public/500.html</tt>.
|
6
8
|
# If an internationalized locale is set, this middleware will attempt to render
|
7
|
-
# the template in
|
8
|
-
# is not found it will fall back on
|
9
|
+
# the template in <tt>/public/500.<locale>.html</tt>. If an internationalized template
|
10
|
+
# is not found it will fall back on <tt>/public/500.html</tt>.
|
9
11
|
#
|
10
12
|
# When a request with a content type other than HTML is made, this middleware
|
11
13
|
# will attempt to convert error information into the appropriate response type.
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "ipaddr"
|
2
4
|
|
3
5
|
module ActionDispatch
|
@@ -10,7 +12,7 @@ module ActionDispatch
|
|
10
12
|
# by @gingerlime. A more detailed explanation of the algorithm is given
|
11
13
|
# at GetIp#calculate_ip.
|
12
14
|
#
|
13
|
-
# Some Rack servers concatenate repeated headers, like {HTTP RFC 2616}[
|
15
|
+
# Some Rack servers concatenate repeated headers, like {HTTP RFC 2616}[https://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2]
|
14
16
|
# requires. Some Rack servers simply drop preceding headers, and only report
|
15
17
|
# the value that was {given in the last header}[http://andre.arko.net/2011/12/26/repeated-headers-and-ruby-web-servers].
|
16
18
|
# If you are behind multiple proxy servers (like NGINX to HAProxy to Unicorn)
|
@@ -29,7 +31,7 @@ module ActionDispatch
|
|
29
31
|
# The default trusted IPs list simply includes IP addresses that are
|
30
32
|
# guaranteed by the IP specification to be private addresses. Those will
|
31
33
|
# not be the ultimate client IP in production, and so are discarded. See
|
32
|
-
#
|
34
|
+
# https://en.wikipedia.org/wiki/Private_network for details.
|
33
35
|
TRUSTED_PROXIES = [
|
34
36
|
"127.0.0.1", # localhost IPv4
|
35
37
|
"::1", # localhost IPv6
|
@@ -157,13 +159,13 @@ module ActionDispatch
|
|
157
159
|
|
158
160
|
def ips_from(header) # :doc:
|
159
161
|
return [] unless header
|
160
|
-
# Split the comma-separated list into an array of strings
|
162
|
+
# Split the comma-separated list into an array of strings.
|
161
163
|
ips = header.strip.split(/[,\s]+/)
|
162
164
|
ips.select do |ip|
|
163
165
|
begin
|
164
|
-
# Only return IPs that are valid according to the IPAddr#new method
|
166
|
+
# Only return IPs that are valid according to the IPAddr#new method.
|
165
167
|
range = IPAddr.new(ip).to_range
|
166
|
-
#
|
168
|
+
# We want to make sure nobody is sneaking a netmask in.
|
167
169
|
range.begin == range.end
|
168
170
|
rescue ArgumentError
|
169
171
|
nil
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "rack/utils"
|
2
4
|
require "rack/request"
|
3
5
|
require "rack/session/abstract/id"
|
@@ -53,7 +55,7 @@ module ActionDispatch
|
|
53
55
|
rescue ArgumentError => argument_error
|
54
56
|
if argument_error.message =~ %r{undefined class/module ([\w:]*\w)}
|
55
57
|
begin
|
56
|
-
# Note that the regexp does not allow $1 to end with a ':'
|
58
|
+
# Note that the regexp does not allow $1 to end with a ':'.
|
57
59
|
$1.constantize
|
58
60
|
rescue LoadError, NameError
|
59
61
|
raise ActionDispatch::Session::SessionRestoreError
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "active_support/core_ext/hash/keys"
|
2
4
|
require "action_dispatch/middleware/session/abstract_store"
|
3
5
|
require "rack/session/cookie"
|
@@ -19,39 +21,25 @@ module ActionDispatch
|
|
19
21
|
# knowing your app's secret key, but can easily read their +user_id+. This
|
20
22
|
# was the default for Rails 3 apps.
|
21
23
|
#
|
22
|
-
#
|
24
|
+
# Your cookies will be encrypted using your apps secret_key_base. This
|
23
25
|
# goes a step further than signed cookies in that encrypted cookies cannot
|
24
26
|
# be altered or read by users. This is the default starting in Rails 4.
|
25
27
|
#
|
26
|
-
#
|
27
|
-
# be encrypted, and signed cookies generated by Rails 3 will be
|
28
|
-
# transparently read and encrypted to provide a smooth upgrade path.
|
29
|
-
#
|
30
|
-
# Configure your session store in config/initializers/session_store.rb:
|
28
|
+
# Configure your session store in <tt>config/initializers/session_store.rb</tt>:
|
31
29
|
#
|
32
30
|
# Rails.application.config.session_store :cookie_store, key: '_your_app_session'
|
33
31
|
#
|
34
|
-
#
|
35
|
-
#
|
36
|
-
#
|
37
|
-
# secret_key_base: 'secret key'
|
38
|
-
#
|
39
|
-
# To generate a secret key for an existing application, run `rails secret`.
|
32
|
+
# By default, your secret key base is derived from your application name in
|
33
|
+
# the test and development environments. In all other environments, it is stored
|
34
|
+
# encrypted in the <tt>config/credentials.yml.enc</tt> file.
|
40
35
|
#
|
41
|
-
# If
|
42
|
-
#
|
43
|
-
# Note that you should wait to set secret_key_base until you have 100% of
|
44
|
-
# your userbase on Rails 4 and are reasonably sure you will not need to
|
45
|
-
# rollback to Rails 3. This is because cookies signed based on the new
|
46
|
-
# secret_key_base in Rails 4 are not backwards compatible with Rails 3.
|
47
|
-
# You are free to leave your existing secret_token in place, not set the
|
48
|
-
# new secret_key_base, and ignore the deprecation warnings until you are
|
49
|
-
# reasonably sure that your upgrade is otherwise complete. Additionally,
|
50
|
-
# you should take care to make sure you are not relying on the ability to
|
51
|
-
# decode signed cookies generated by your app in external applications or
|
52
|
-
# JavaScript before upgrading.
|
36
|
+
# If your application was not updated to Rails 5.2 defaults, the secret_key_base
|
37
|
+
# will be found in the old <tt>config/secrets.yml</tt> file.
|
53
38
|
#
|
54
|
-
# Note that changing
|
39
|
+
# Note that changing your secret_key_base will invalidate all existing session.
|
40
|
+
# Additionally, you should take care to make sure you are not relying on the
|
41
|
+
# ability to decode signed cookies generated by your app in external
|
42
|
+
# applications or JavaScript before changing it.
|
55
43
|
#
|
56
44
|
# Because CookieStore extends Rack::Session::Abstract::Persisted, many of the
|
57
45
|
# options described there can be used to customize the session cookie that
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "action_dispatch/http/request"
|
2
4
|
require "action_dispatch/middleware/exception_wrapper"
|
3
5
|
|
@@ -8,7 +10,7 @@ module ActionDispatch
|
|
8
10
|
# The exceptions app should be passed as parameter on initialization
|
9
11
|
# of ShowExceptions. Every time there is an exception, ShowExceptions will
|
10
12
|
# store the exception in env["action_dispatch.exception"], rewrite the
|
11
|
-
# PATH_INFO to the exception status code and call the
|
13
|
+
# PATH_INFO to the exception status code and call the Rack app.
|
12
14
|
#
|
13
15
|
# If the application returns a "X-Cascade" pass response, this middleware
|
14
16
|
# will send an empty response as result with the correct status code.
|
@@ -1,47 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActionDispatch
|
2
|
-
# This middleware is added to the stack when
|
3
|
-
# the options set in
|
4
|
+
# This middleware is added to the stack when <tt>config.force_ssl = true</tt>, and is passed
|
5
|
+
# the options set in +config.ssl_options+. It does three jobs to enforce secure HTTP
|
4
6
|
# requests:
|
5
7
|
#
|
6
|
-
#
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
8
|
+
# 1. <b>TLS redirect</b>: Permanently redirects +http://+ requests to +https://+
|
9
|
+
# with the same URL host, path, etc. Enabled by default. Set +config.ssl_options+
|
10
|
+
# to modify the destination URL
|
11
|
+
# (e.g. <tt>redirect: { host: "secure.widgets.com", port: 8080 }</tt>), or set
|
12
|
+
# <tt>redirect: false</tt> to disable this feature.
|
13
|
+
#
|
14
|
+
# Requests can opt-out of redirection with +exclude+:
|
11
15
|
#
|
12
|
-
#
|
16
|
+
# config.ssl_options = { redirect: { exclude: -> request { request.path =~ /healthcheck/ } } }
|
13
17
|
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
18
|
+
# 2. <b>Secure cookies</b>: Sets the +secure+ flag on cookies to tell browsers they
|
19
|
+
# must not be sent along with +http://+ requests. Enabled by default. Set
|
20
|
+
# +config.ssl_options+ with <tt>secure_cookies: false</tt> to disable this feature.
|
17
21
|
#
|
18
|
-
#
|
19
|
-
#
|
20
|
-
#
|
22
|
+
# 3. <b>HTTP Strict Transport Security (HSTS)</b>: Tells the browser to remember
|
23
|
+
# this site as TLS-only and automatically redirect non-TLS requests.
|
24
|
+
# Enabled by default. Configure +config.ssl_options+ with <tt>hsts: false</tt> to disable.
|
21
25
|
#
|
22
|
-
#
|
23
|
-
# * `expires`: How long, in seconds, these settings will stick. The minimum
|
24
|
-
# required to qualify for browser preload lists is `18.weeks`. Defaults to
|
25
|
-
# `180.days` (recommended).
|
26
|
-
# * `subdomains`: Set to `true` to tell the browser to apply these settings
|
27
|
-
# to all subdomains. This protects your cookies from interception by a
|
28
|
-
# vulnerable site on a subdomain. Defaults to `true`.
|
29
|
-
# * `preload`: Advertise that this site may be included in browsers'
|
30
|
-
# preloaded HSTS lists. HSTS protects your site on every visit *except the
|
31
|
-
# first visit* since it hasn't seen your HSTS header yet. To close this
|
32
|
-
# gap, browser vendors include a baked-in list of HSTS-enabled sites.
|
33
|
-
# Go to https://hstspreload.appspot.com to submit your site for inclusion.
|
34
|
-
# Defaults to `false`.
|
26
|
+
# Set +config.ssl_options+ with <tt>hsts: { ... }</tt> to configure HSTS:
|
35
27
|
#
|
36
|
-
#
|
37
|
-
#
|
38
|
-
#
|
39
|
-
# `hsts: { expires: 0 }`.
|
28
|
+
# * +expires+: How long, in seconds, these settings will stick. The minimum
|
29
|
+
# required to qualify for browser preload lists is 18 weeks. Defaults to
|
30
|
+
# 180 days (recommended).
|
40
31
|
#
|
41
|
-
#
|
32
|
+
# * +subdomains+: Set to +true+ to tell the browser to apply these settings
|
33
|
+
# to all subdomains. This protects your cookies from interception by a
|
34
|
+
# vulnerable site on a subdomain. Defaults to +true+.
|
42
35
|
#
|
43
|
-
#
|
36
|
+
# * +preload+: Advertise that this site may be included in browsers'
|
37
|
+
# preloaded HSTS lists. HSTS protects your site on every visit <i>except the
|
38
|
+
# first visit</i> since it hasn't seen your HSTS header yet. To close this
|
39
|
+
# gap, browser vendors include a baked-in list of HSTS-enabled sites.
|
40
|
+
# Go to https://hstspreload.org to submit your site for inclusion.
|
41
|
+
# Defaults to +false+.
|
42
|
+
#
|
43
|
+
# To turn off HSTS, omitting the header is not enough. Browsers will remember the
|
44
|
+
# original HSTS directive until it expires. Instead, use the header to tell browsers to
|
45
|
+
# expire HSTS immediately. Setting <tt>hsts: false</tt> is a shortcut for
|
46
|
+
# <tt>hsts: { expires: 0 }</tt>.
|
44
47
|
class SSL
|
48
|
+
# :stopdoc:
|
49
|
+
|
45
50
|
# Default to 180 days, the low end for https://www.ssllabs.com/ssltest/
|
46
51
|
# and greater than the 18-week requirement for browser preload lists.
|
47
52
|
HSTS_EXPIRES_IN = 15552000
|
@@ -67,7 +72,7 @@ module ActionDispatch
|
|
67
72
|
if request.ssl?
|
68
73
|
@app.call(env).tap do |status, headers, body|
|
69
74
|
set_hsts_header! headers
|
70
|
-
flag_cookies_as_secure! headers if @secure_cookies
|
75
|
+
flag_cookies_as_secure! headers if @secure_cookies
|
71
76
|
end
|
72
77
|
else
|
73
78
|
return redirect_to_https request unless @exclude.call(request)
|
@@ -94,9 +99,9 @@ module ActionDispatch
|
|
94
99
|
end
|
95
100
|
end
|
96
101
|
|
97
|
-
#
|
102
|
+
# https://tools.ietf.org/html/rfc6797#section-6.1
|
98
103
|
def build_hsts_header(hsts)
|
99
|
-
value = "max-age=#{hsts[:expires].to_i}"
|
104
|
+
value = "max-age=#{hsts[:expires].to_i}".dup
|
100
105
|
value << "; includeSubDomains" if hsts[:subdomains]
|
101
106
|
value << "; preload" if hsts[:preload]
|
102
107
|
value
|
@@ -135,7 +140,7 @@ module ActionDispatch
|
|
135
140
|
host = @redirect[:host] || request.host
|
136
141
|
port = @redirect[:port] || request.port
|
137
142
|
|
138
|
-
location = "https://#{host}"
|
143
|
+
location = "https://#{host}".dup
|
139
144
|
location << ":#{port}" if port != 80 && port != 443
|
140
145
|
location << request.fullpath
|
141
146
|
location
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "rack/utils"
|
2
4
|
require "active_support/core_ext/uri"
|
3
5
|
|
@@ -6,11 +8,11 @@ module ActionDispatch
|
|
6
8
|
# When initialized, it can accept optional HTTP headers, which will be set
|
7
9
|
# when a response containing a file's contents is delivered.
|
8
10
|
#
|
9
|
-
# This middleware will render the file specified in
|
11
|
+
# This middleware will render the file specified in <tt>env["PATH_INFO"]</tt>
|
10
12
|
# where the base path is in the +root+ directory. For example, if the +root+
|
11
|
-
# is set to
|
12
|
-
#
|
13
|
-
# located at
|
13
|
+
# is set to +public/+, then a request with <tt>env["PATH_INFO"]</tt> of
|
14
|
+
# +assets/application.js+ will return a response with the contents of a file
|
15
|
+
# located at +public/assets/application.js+ if the file exists. If the file
|
14
16
|
# does not exist, a 404 "File not Found" response will be returned.
|
15
17
|
class FileHandler
|
16
18
|
def initialize(root, index: "index", headers: {})
|
@@ -23,8 +25,8 @@ module ActionDispatch
|
|
23
25
|
# correct read permissions, the return value is a URI-escaped string
|
24
26
|
# representing the filename. Otherwise, false is returned.
|
25
27
|
#
|
26
|
-
# Used by the
|
27
|
-
# in the server's
|
28
|
+
# Used by the +Static+ class to check the existence of a valid file
|
29
|
+
# in the server's +public/+ directory (see Static#call).
|
28
30
|
def match?(path)
|
29
31
|
path = ::Rack::Utils.unescape_path path
|
30
32
|
return false unless ::Rack::Utils.valid_path? path
|
@@ -33,7 +35,7 @@ module ActionDispatch
|
|
33
35
|
paths = [path, "#{path}#{ext}", "#{path}/#{@index}#{ext}"]
|
34
36
|
|
35
37
|
if match = paths.detect { |p|
|
36
|
-
path = File.join(@root, p.force_encoding(Encoding::UTF_8))
|
38
|
+
path = File.join(@root, p.dup.force_encoding(Encoding::UTF_8))
|
37
39
|
begin
|
38
40
|
File.file?(path) && File.readable?(path)
|
39
41
|
rescue SystemCallError
|
@@ -99,7 +101,7 @@ module ActionDispatch
|
|
99
101
|
# This middleware will attempt to return the contents of a file's body from
|
100
102
|
# disk in the response. If a file is not found on disk, the request will be
|
101
103
|
# delegated to the application stack. This middleware is commonly initialized
|
102
|
-
# to serve assets from a server's
|
104
|
+
# to serve assets from a server's +public/+ directory.
|
103
105
|
#
|
104
106
|
# This middleware verifies the path to ensure that only files
|
105
107
|
# living in the root directory can be rendered. A request cannot
|