Build 2 middleware stacks in Rails app

2020-02-15 01:49发布

问题:

I have a Rails app provides both website and api.
I don't want some elements appear in API's middleware stack, for example : ActionDispatch::Cookies, ActionDispatch::Session::CookieStore or ActionDispatch::Flash.
Website's middleware stack is remain as normal.

So how could I do that? Thanks.

回答1:

I had exactly the same situation, and wanted to do the same thing. So far I have been able to use a Rails Engine to add middleware that is missing without problems for certain routes (although it is not necessarily in the "right order" in the stack, but so far it seems to be working okay):

application.rb:

# after Bundler.require(...)
require_relative '../lib/engines/website/lib/website'

lib/engines/website/lib/website.rb:

require_relative "website/engine"

module Website; end

lib/engines/website/lib/website/engine.rb:

module Website
  class Engine < ::Rails::Engine
    middleware.use ActionDispatch::Cookies
    middleware.use ActionDispatch::Session::CookieStore
    middleware.use ActionDispatch::Flash
  end
end

config/routes.rb:

mount Website::Engine => "/website"

(or you can mount at "/", but define your other routes first in that case)

And everything for the website goes in the typical directory structure under the engine directory:

lib
  engines
    website
      app
        assets
          ...
        controllers
          ...
        views
          ...
      config
        routes.rb
      lib
        website
        website.rb

I haven't gotten very far yet, but so far this is working for me.

Note: Technically, the engine file doesn't even have to be a separate file in the website directory. You could just shove it into website.rb and make it a one-file-wonder if there's nothing else particularly complicated to add to your lib directory. The only requirement I've found is that the file does have to be in a lib directory inside the engine's own named directory (theoretically containing config/routes.rb and the rest of the engine's file structure), because when a Rails::Engine is eager-loaded by the app, the engine looks for its lib directory to find the adjacent app, config, vendor, etc. to eager-load.