Previously, we were able to force_ssl to specific controller actions by using force_ssl callback at controller level. Rails 6 deprecates this option setting at controller level. This option to force_ssl is now available only at Rails application configuration level only.
Before Rails 6
Let’s say, we have a resource configured for posts.
# config/routes.rb
resources :posts
The controller has actions as given below.
- Index action to list available posts
- Create action to create a new post
class PostsController < ApplicationController
def index
# code to return list of available posts
end
def create
# code to create a new post
end
end
Let’s say, we want to create an action to be accessed with ssl only.
This can be enforced using force_ssl
option available
as a callback at controller level with code given below.
class PostsController < ApplicationController
force_ssl only: [:create]
def index
# code to return list of available posts
end
def create
# code to create a new post
end
end
As we can see,
we have specified force_ssl with options only: [:index]
,
this means Rails will force requests to use ssl protocol only
for create action on posts controller.
Now, if we try to create a new post without using ssl then, it will throw an error as given below.
Filter chain halted as actionpack-5.1.5/lib/action_controller/metal/force_ssl.rb:65> rendered or redirected
Completed 301 Moved Permanently
After Rails 6
Rails 6 encourages us to use force_ssl option at config level to enable ssl throughout our application. We can set this option as given below.
# config/environments/production.rb
config.force_ssl = true
If we still use, force_ssl at controller level, it still works as expected but Rails throws a deprecation warning as given below.
DEPRECATION WARNING: Controller-level `force_ssl` is deprecated and will be removed from Rails 6.1. Please enable `config.force_ssl` in your environment configuration to enable the ActionDispatch::SSL middleware to more fully enforce that your application communicate over HTTPS. If needed, you can use `config.ssl_options` to exempt matching endpoints from being redirected to HTTPS. (called from <class:ConsumerController> at /Users/akshay/workplace/fiormarkets/app/controllers/consumer_controller.rb:5)
If we still want to disable ssl verification for certain endpoints, then we can use ssl_options at config level to achieve such behavior.
config.ssl_options = {
redirect: {
exclude: -> request { request.post? && request.path =~ /posts/ }
}
}
This code block tells router to redirect to use ssl if request is of type post and includes posts path in ther request path.