HOWTO Put a controller under a SSL subdomain

Let’s imagine that you need to create a secure login area, for example if you own you may want to put the user login page on How can you do it?

The best solution in my opinion is to put all the login procedures in a dedicated login controller (eg the ‘sessions’ controller if you are using the RESTful authentication plugin) and then modify a bit the url_for method in order to modify the calls to that controller.

Part 1, A little configuration.

In our environment.rb we’re going to create an array with the name of the controllers we want to put under a different subdomain and under SSL:

SECURE_MODE = [ /\/sessions$/ ].freeze

SECURE_SUBDOMAIN = "secure".freeze

Part 2, Url_for tweaking

Then in our application.rb we have to tweak a bit the url_for function in order to let the defined controllers being handled correctly.

def url_for(options = {}, *parameters_for_method_reference)

tmp_result = super((options.is_a?(Hash) ? options.merge({:only_path => false})

: options), parameters_for_method_reference)

if not (tmp_result =~

# this tweak is necessary just beacuse I use WebBrick for my development environment (aka I need to specify the port)

if ENV['RAILS_ENV'] == ‘production’

cut_result = tmp_result.to_s.gsub("#{request.protocol}# {}") ,"" )

elsif ENV['RAILS_ENV'] == ‘development’

cut_result = tmp_result.to_s.gsub("#{request.protocol}# {request.host_with_port}"), "" )


# We’re going to talk about this function later

url_to_go = dispatch_ssl(cut_result)


super((url_to_go.nil? ? tmp_result : url_to_go), parameters_for_method_reference)


Part 3 Dispatching urls

dispatch_ssl is a function I wrote that receive a partial url (eg /session) and returns the path modified in order to match the new subdomain and protocol rules.

def dispatch_ssl(tmp_result = request.request_uri)

subdomain = SECURE_SUBDOMAIN.blank? ? "" : SECURE_SUBDOMAIN + "."

# need secure is a function that simply check if this path need to be put under SSL

if need_secure?(tmp_result)

if request.protocol == ‘http://’

url_to_go = "https://#{subdomain}" + + tmp_result



if request.protocol == ‘https://’

host =,"")

url_to_go = ‘http://’ + host + tmp_result



return url_to_go


Last but not Least: need_secure? and ssl_require

The first function is used by dispatch_ssl to check if the current url match the SECURE_MODE array, the second one (ssl_require) have to be called in a before_filter directive and detects if the user is trying to access a secure area without the correct subdomain and protocol; if this happens the user will be redirected to the correct url.

def need_secure?(uri)

SECURE_MODE.each{ |s|

a = (uri =~ s)

return true unless a.nil?


return false;


def ssl_required

if not (redir = dispatch_ssl.to_s).blank?

redirect_to(redir) and return false



Leave a Comment