Rails - How to Redirect from http://example.com to https://www.example.com

25,577

Solution 1

DNS records cannot define the protocol for a domain, therefore you can't redirect http:// to https:// through DNS. Doing it through the web server configuration is not portable, hard to do, error prone and just plain outdated. This is a job best handled by the Rails router.

# beginning of routes.rb 
match "*path" => redirect("https://www.mysite.com/%{path}"), :constraints => { :protocol => "http://" }
match "*path" => redirect("https://www.mysite.com/%{path}"), :constraints => { :subdomain => "" }

Solution 2

As an extension to user2100689's answer, in Rails 3+ you can use config.force_ssl = true in config/environments/production.rb

The line can just be uncommented as follows

# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
config.force_ssl = true

Solution 3

Rails 3.1.0 and higher has force_ssl, which is a controller method that will redirect to https for non-development environments.

http://api.rubyonrails.org/classes/ActionController/ForceSSL/ClassMethods.html

Place it in each controller that you want to redirect, or better yet, place it in your ApplicationController:

app/controllers/application.rb:

class ApplicationController < ActionController::Base
  # ...
  force_ssl
  # ...
end

This is a good thing to always include in your apps (and of course you'll have to get a certificate). HTTPS Everywhere!

Solution 4

You can always throw this in your production.rb... config.use_ssl = true

Solution 5

Because this is Heroku, you cannot use apache or nginx configs. What you can do is put a before_filter in your ApplicationController, assuming you have 3 or more controllers like these below, although of course they will be in separate files

class ApplicationController < ActionController::Base
    def redirect_https        
        redirect_to :protocol => "https://" unless request.ssl?
        return true
    end
    before_filter :redirect_https
end
class TypicalController < ApplicationController
    def blah
    end
end
class HomePageController < ApplicationController
    skip_before_filter :redirect_https
end

You may also need to fiddle your routes a bit when using devise, but I suspect that was just the way we did it so I won't get into those details here, and I've modified the code above to avoid that complication.

happy hacking.

Share:
25,577
AnApprentice
Author by

AnApprentice

working on Matter, a new way to gather professional feedback.

Updated on February 08, 2020

Comments

  • AnApprentice
    AnApprentice about 4 years

    I'm looking to learn how to cleanup my app's URLs. My app is powered by Rails 3 on Heroku.

    The desired URL is https://www.example.comite.com

    I'd like to redirect all URLs unlike the above to that URL. Is this a Rails thing or DNS?

    Bad URLs:

    https://example.comite.com
    http://www.example.comite.com
    http://example.comite.com
    

    And if anything is trailing, like http://www.example.comite.com/photo/1 for the url to be redirected with the path: https://www.example.comite.com/photo/1

  • theandym
    theandym over 13 years
    He's using Heroku and has no access to the web server config like that.
  • fearless_fool
    fearless_fool over 12 years
    This feels like the right way to go, but doesn't answer one key point: how do you transition from http://mysite.com to https://www.mysite.com? (Answer the essentially identical question in stackoverflow.com/questions/9027916/… and get double points!)
  • Mindey I.
    Mindey I. almost 12 years
    This works, but do you need to leave the A records in place? I was assuming you'd be able to redirect mysite.com to http://www.mysite.com via DNS, and then once it hit your rails app it would redirect to https using your route contraints. However, with my DNS redirect http://mysite.com redirects as expected, but https://mysite.com doesn't (and never hits my rails server for the route contraints to take effect). I've reverted back to having A records for now, but was just wondering if you knew why the DNS redirect didn't work for https://mysite.com.
  • edgerunner
    edgerunner almost 12 years
    there's nothing you can do on the DNS side. As I said, DNS has nothing to do with the protocol. You can redirect a name to another, but not the protocol. It isn't even transmitted to the DNS server. Your browser asks the IP address of mysite.com not http://mysite.com, and it gets a reply like REDIRECT www.mysite.com not REDIRECT http://www.mysite.com
  • stephenmurdoch
    stephenmurdoch over 10 years
    Does this protect against SSL stripping?
  • Robin Daugherty
    Robin Daugherty over 10 years
    I believe this does protect against sslstrip-type attacks. Rails will refuse to serve non-SSL requests by always redirecting to the corresponding HTTPS URL. If sslstrip changes the protocol of the redirect, Rails will simply redirect to HTTPS again.
  • stephenmurdoch
    stephenmurdoch over 10 years
    Thanks @Robin_Daughtery
  • Simon B.
    Simon B. about 7 years
    @RobinDaugherty CAREFUL, if there is a MITM attack then session cookies will be leaked before the redirect back to https happens. Which means a more advanced sslstrip will pwn your site, and make public wifi's (and spoofed wifis) very dangerous while using your app. To prevent cookies leaking, you need to enable config.use_ssl = true
  • Robin Daugherty
    Robin Daugherty about 7 years
    force_ssl is the setting that enables secure cookies. I can find no reference to a use_ssl setting in the Rails codebase, nor in Google.
  • Robin Daugherty
    Robin Daugherty about 7 years
    With Rails 5 (and possibly older versions as well), use_ssl will do nothing. force_ssl is the option that must be set.
  • Shrinivas
    Shrinivas over 6 years
    I am not able to redirect from "example.com" to "example.com" by adding above rules in routes
  • edgerunner
    edgerunner over 4 years
    @Shrinivas they probably won't work unless you put them at the beginning of your routes.rb