Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SSL-specific hostname in Heroku with Rails 3.1

I currently have a setup where I force SSL or http where I need it with this before_filter in my application controller:

def force_ssl
  if params[:controller] == "sessions"
    if !request.ssl? && Rails.env.production?
      redirect_to :protocol => 'https://', :status => :moved_permanently
    end
  else
    if request.ssl? && Rails.env.production?
      redirect_to :protocol => 'http://', :status => :moved_permanently
    end
  end
end

What I'd like to do is to use https://secure.example.com when using SSL but keep using http://example.com when not using SSL. Is there a way I can switch between the hostnames depending on whether I'm using SSL?

like image 629
Eric Yang Avatar asked Oct 10 '22 06:10

Eric Yang


1 Answers

First I'll show how to force SSL in current and earlier versions of Rails, then at the end I've posted how to use HTTP and HTTPS in Parallel with each other, which is what I think your looking for.

Rails >= 3.1

Simply use config.force_ssl = true in your environment configuration.

# config/application.rb
module MyApp
  class Application < Rails::Application
    config.force_ssl = true
  end
end

You can also selectively enable https depending on the current Rails environment. For example, you might want to keep HTTPS turned off on development, and enable it on staging/production.

# config/application.rb
module MyApp
  class Application < Rails::Application
    config.force_ssl = false
  end
end

# config/environments/production.rb
MyApp::Application.configure do
  config.force_ssl = true
end

Rails < 3.1

Just in case you have any projects that are not Rails 3.1 and want the same feature. Enable HTTPS by adding the following line to your environment configuration.

config.middleware.insert_before ActionDispatch::Static, "Rack::SSL"

Note that I’m passing Rack::SSL as string to delegate the loading of the class at the end of the Rails application initialization. Also note the middleware must be inserted in a specific position in the stack, at least before ActionDispatch::Static and ActionDispatch::Cookies.

Don’t forget to define Rack::SSL dependency in your Gemfile.

# Gemfile
gem 'rack-ssl', :require => 'rack/ssl'

Enabling HTTPS and HTTP in parallel

Rack::SSL has a very interesting and undocumented feature. You can pass an :exclude option to determine when to enable/disable the use of HTTPS.

The following code enables Rack::SSL and all its filters only in case the request comes from a HTTPS connection.

config.middleware.insert_before ActionDispatch::Static, Rack::SSL, :exclude => proc { |env| env['HTTPS'] != 'on' }

Both the following URLs will continue to work, but the first one will trigger the Rack::SSL filters.

https://secure.example.com
http://example.com

like image 80
Donavan White Avatar answered Oct 13 '22 11:10

Donavan White