views:

1129

answers:

4

Hi everyone,

I'm maintaining a Ruby on Rails site and I'm confused as to how to perform redirects to relative URLs using the https protocol.

I can successfully create a redirect to a relative URL using http, for example:

redirect_to "/some_directory/"

But I cannot discern how to create a redirect to a URL using the https protocol. I have only been able to do so by using absolute URLS, for example:

redirect_to "https://mysite.com/some_directory/"

I would like to keep my code clean, and using relative URLs seems like a good idea. Does anyone know how to achieve this in Rails?

A: 

Open the class that has redirect_to and add a method redirect_to_secure_of with an appropriate implementation. Then call:

redirect_to_secure_of "/some_directory/"

Put this method in the lib directory or somewhere useful.

Justice
Thanks, but I'm looking for a little more detail than "an appropriate implementation."
X3Maverick
Sorry, I thought you were asking how to make the *calling* code clean.
Justice
A: 

Relative URLs, by definition, use the current protocol and host. If you want to change the protocol being used, you need to supply the absolute URL. I would take Justice's advice and create a method that does this for you:

def redirect_to_secure(relative_uri)
  redirect_to "https://" + request.host + relative_uri
end
Michael Sepcot
A: 

The ActionController::Base#redirect_to method takes an options hash, one of the parameters of which is :protocol which allows you to call:

redirect_to :protocol => 'https://', 
            :controller => 'some_controller', 
            :action => 'index'

See the definition for #redirect_to and #url_for for more info on the options.


Alternatively, and especially if SSL is to be used for all your controller actions, you could take a more declarative approach using a before_filter. In ApplicationController you could define the following method:

def redirect_to_https
    redirect_to :protocol => "https://" unless (request.ssl? || local_request?)
end

You can then add filters in your those controllers which have actions requiring SSL, e.g:

class YourController
    before_filter :redirect_to_https, :only => ["index", "show"]
end

Or, if you require SSL across your entire app, declare the filter in ApplicationController:

class ApplicationController
    before_filter :redirect_to_https
end
Olly
You can use `:protocol => 'https://'` iff you are passing a hash to `redirect_to` if you are passing a relative URL like in the question above, that will not work. I agree that a `before_filter` is the better way to go in general.
Michael Sepcot
+1  A: 

You're probably better off using ssl_requirement and not caring if a link or redirect is or isn't using https. With ssl_requirement, you declare which actions require SSL, which ones are capable of SSL and which ones are required not to use SSL.

If you're redirecting somewhere outside of your Rails app, then specifying the protocol as Olly suggests will work.

Andy Gaskell