Rails API Application compatibility (and support) #4947
Description
This issue is meant to track compatibility and support for 'Rails API Applications' by which I specifically mean Rails applications built with API only support, ala
Rails.application.config.api_only = true
Reference: https://guides.rubyonrails.org/api_app.html
Current behavior
With a boilerplate rails app built with api-only support (rails new my_api --api
) devise throws some errors under testing, mainly from missing middleware that is not provided for api-only applications.
At first look, the main culprits tend to be the flash middleware and redirect/cookie middlewares.
Expected behavior
Devise should treat all requests as 'non-navigational' and 'non-flashing' if loaded within a Rails api-only application without configuration (assuming it can be done while maintaining full compatibility with a 'full' rails application)
Proposal
I've looked into this issue with a dummy rails-api app, and as I pointed out about, much of it has to do with missing middleware. Luckily, most of the calls to that middleware are guarded in the current code by the helper methods is_navigational_format?
and is_flashing_format?
(the later is by default just a call to the former). I'm suggesting that we make is_flashing_format?
aware of the type of application it is loaded into.
How to determine the nature of the rails application is a bit tricky, which at least 3 ways I can see:
- Presence of and value of
Rails.application.config.api_only
- Detecting loaded middleware
- Detecting the parent controller
Detecting Rails.application.config.api_only
can be troublesome as many applications could be hybrids, consisting of both api-only and non-api controllers. This also puts a big assumption that legacy applications have properly and fully migrated over their configuration.
Detecting loaded middleware is also troublesome, as we can't tell if the middleware is loaded due to the nature of the controller, or, like devise does itself, loaded manually as a 'helper library' of behavior.
Detecting the parent controller I think, is the best solution with the least probability of false positives. Not constrained to just the direct parent ala Devise.parent_controller.constantize
, but we should be able to say that if ActionController::API
is in the hierarchy, we should treat it as an API controller, and not attempt to flash or set cookies (API controllers allow for redirects).
Again, my goal is not to change devise to be api-centric, just to make it reasonably work with api apps out of the box without errors.