From 97b9e32d236bba5c5b2e18c1781066fa94b9f885 Mon Sep 17 00:00:00 2001 From: Greg Molnar Date: Sun, 28 Feb 2016 22:48:36 +0100 Subject: [PATCH] add `constraint_to` option to SSL middleware --- actionpack/lib/action_dispatch/middleware/ssl.rb | 8 ++++++-- actionpack/test/dispatch/ssl_test.rb | 7 +++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/actionpack/lib/action_dispatch/middleware/ssl.rb b/actionpack/lib/action_dispatch/middleware/ssl.rb index 711d8b016a..cb442af19b 100644 --- a/actionpack/lib/action_dispatch/middleware/ssl.rb +++ b/actionpack/lib/action_dispatch/middleware/ssl.rb @@ -34,6 +34,10 @@ module ActionDispatch # original HSTS directive until it expires. Instead, use the header to tell browsers to # expire HSTS immediately. Setting `hsts: false` is a shortcut for # `hsts: { expires: 0 }`. + # + # Redirection can be constrained to only whitelisted requests with `constrain_to`: + # + # config.ssl_options = { redirect: { constrain_to: -> request { request.path !~ /healthcheck/ } } } class SSL # Default to 180 days, the low end for https://www.ssllabs.com/ssltest/ # and greater than the 18-week requirement for browser preload lists. @@ -55,7 +59,7 @@ def initialize(app, redirect: {}, hsts: {}, secure_cookies: true, **options) else @redirect = redirect end - + @constrain_to = @redirect && @redirect[:constrain_to] || proc { @redirect } @secure_cookies = secure_cookies if hsts != true && hsts != false && hsts[:subdomains].nil? @@ -80,7 +84,7 @@ def call(env) flag_cookies_as_secure! headers if @secure_cookies end else - return redirect_to_https request if @redirect + return redirect_to_https request if @constrain_to.call(request) @app.call(env) end end diff --git a/actionpack/test/dispatch/ssl_test.rb b/actionpack/test/dispatch/ssl_test.rb index 18ff894b31..bb2125e485 100644 --- a/actionpack/test/dispatch/ssl_test.rb +++ b/actionpack/test/dispatch/ssl_test.rb @@ -39,6 +39,13 @@ def assert_redirected(redirect: {}, deprecated_host: nil, deprecated_port: nil, assert_equal redirect[:body].join, @response.body end + test 'constrain to can avoid redirect' do + constraining = { constrain_to: -> request { request.path !~ /healthcheck/ } } + + assert_not_redirected 'http://example.org/healthcheck', redirect: constraining + assert_redirected from: 'http://example.org/', redirect: constraining + end + test 'https is not redirected' do assert_not_redirected 'https://example.org' end