From f99ce3c188f5dde57e2ff63e6a22363c62f0a4cd Mon Sep 17 00:00:00 2001 From: Andrew White Date: Thu, 25 Apr 2013 13:40:53 +0100 Subject: Add support for extra options to `force_ssl` This commit adds support for passing additional url options along with a :status option and any of the flash-related options to `redirect_to` (i.e. :flash, :alert & :notice). Closes #7570. --- .../lib/action_controller/metal/force_ssl.rb | 65 ++++++++++++++++------ 1 file changed, 48 insertions(+), 17 deletions(-) (limited to 'actionpack/lib/action_controller/metal') diff --git a/actionpack/lib/action_controller/metal/force_ssl.rb b/actionpack/lib/action_controller/metal/force_ssl.rb index fe61dd1f86..7edeba6fc0 100644 --- a/actionpack/lib/action_controller/metal/force_ssl.rb +++ b/actionpack/lib/action_controller/metal/force_ssl.rb @@ -1,3 +1,6 @@ +require 'active_support/core_ext/hash/except' +require 'active_support/core_ext/hash/slice' + module ActionController # This module provides a method which will redirect browser to use HTTPS # protocol. This will ensure that user's sensitive information will be @@ -14,6 +17,10 @@ module ActionController extend ActiveSupport::Concern include AbstractController::Callbacks + ACTION_OPTIONS = [:only, :except, :if, :unless] + URL_OPTIONS = [:protocol, :host, :domain, :subdomain, :port, :path] + REDIRECT_OPTIONS = [:status, :flash, :alert, :notice] + module ClassMethods # Force the request to this particular controller or specified actions to be # under HTTPS protocol. @@ -29,18 +36,33 @@ module ActionController # end # end # - # ==== Options - # * host - Redirect to a different host name - # * only - The callback should be run only for this action - # * except - The callback should be run for all actions except this action - # * if - A symbol naming an instance method or a proc; the callback - # will be called only when it returns a true value. - # * unless - A symbol naming an instance method or a proc; the callback - # will be called only when it returns a false value. + # ==== URL Options + # You can pass any of the following options to affect the redirect url + # * host - Redirect to a different host name + # * subdomain - Redirect to a different subdomain + # * domain - Redirect to a different domain + # * port - Redirect to a non-standard port + # * path - Redirect to a different path + # + # ==== Redirect Options + # You can pass any of the following options to affect the redirect status and response + # * status - Redirect with a custom status (default is 301 Moved Permanently) + # * flash - Set a flash message when redirecting + # * alert - Set a alert message when redirecting + # * notice - Set a notice message when redirecting + # + # ==== Action Options + # You can pass any of the following options to affect the before_action callback + # * only - The callback should be run only for this action + # * except - The callback should be run for all actions except this action + # * if - A symbol naming an instance method or a proc; the callback + # will be called only when it returns a true value. + # * unless - A symbol naming an instance method or a proc; the callback + # will be called only when it returns a false value. def force_ssl(options = {}) - host = options.delete(:host) - before_action(options) do - force_ssl_redirect(host) + action_options = options.slice(*ACTION_OPTIONS) + before_action(action_options) do + force_ssl_redirect(options.except(*ACTION_OPTIONS)) end end end @@ -48,17 +70,26 @@ module ActionController # Redirect the existing request to use the HTTPS protocol. # # ==== Parameters - # * host - Redirect to a different host name - def force_ssl_redirect(host = nil) + # * host_or_options - Either a host name or any of the url & redirect options + # available to the force_ssl method. + def force_ssl_redirect(host_or_options = nil) unless request.ssl? - secure_url = ActionDispatch::Http::URL.url_for({ + options = { :protocol => 'https://', + :host => request.host, :path => request.fullpath, - :host => host || request.host - }) + :status => :moved_permanently + } + + if host_or_options.is_a?(Hash) + options.merge!(host_or_options) + elsif host_or_options + options.merge!(:host => host_or_options) + end + secure_url = ActionDispatch::Http::URL.url_for(options.slice(*URL_OPTIONS)) flash.keep if respond_to?(:flash) - redirect_to secure_url, :status => :moved_permanently + redirect_to secure_url, options.slice(*REDIRECT_OPTIONS) end end end -- cgit v1.2.3