diff --git a/lib/rage-rb.rb b/lib/rage-rb.rb index 96b30012..76131079 100644 --- a/lib/rage-rb.rb +++ b/lib/rage-rb.rb @@ -7,7 +7,25 @@ module Rage def self.application - Application.new(__router) + app = Application.new(__router) + + config.middleware.middlewares.reverse.inject(app) do |next_in_chain, (middleware, args, block)| + # in Rails compatibility mode we first check if the middleware is a part of the Rails middleware stack; + # if it is - it is expected to be built using `ActionDispatch::MiddlewareStack::Middleware#build` + if Rage.config.internal.rails_mode + rails_middleware = Rails.application.config.middleware.middlewares.find { |m| m.name == middleware.name } + end + + if rails_middleware + rails_middleware.build(next_in_chain) + else + middleware.new(next_in_chain, *args, &block) + end + end + end + + def self.multi_application + Rage::Router::Util::Cascade.new(application, Rails.application) end def self.routes @@ -43,28 +61,8 @@ def self.logger @logger ||= config.logger end - def self.load_middlewares(rack_builder) - config.middleware.middlewares.each do |middleware, args, block| - # in Rails compatibility mode we first check if the middleware is a part of the Rails middleware stack; - # if it is - it is expected to be built using `ActionDispatch::MiddlewareStack::Middleware#build`, but Rack - # expects the middleware to respond to `#new`, so we wrap the middleware into a helper module - if Rage.config.internal.rails_mode - rails_middleware = Rails.application.config.middleware.middlewares.find { |m| m.name == middleware.name } - if rails_middleware - wrapper = Module.new do - extend self - attr_accessor :middleware - def new(app, *, &) - middleware.build(app) - end - end - wrapper.middleware = rails_middleware - middleware = wrapper - end - end - - rack_builder.use(middleware, *args, &block) - end + def self.load_middlewares(_) + puts "`Rage.load_middlewares` is deprecated and has been merged into `Rage.application`. Please remove this call." end def self.code_loader diff --git a/lib/rage/router/backend.rb b/lib/rage/router/backend.rb index 6979e92a..7dcd6d45 100644 --- a/lib/rage/router/backend.rb +++ b/lib/rage/router/backend.rb @@ -68,12 +68,18 @@ def on(method, path, handler, constraints: {}, defaults: nil) raise "Invalid route handler format, expected to match the 'controller#action' pattern" unless handler =~ STRING_HANDLER_REGEXP controller, action = Rage::Router::Util.path_to_class($1), $2 - run_action_method_name = controller.__register_action(action.to_sym) - meta[:controller] = $1 - meta[:action] = $2 + if controller.ancestors.include?(RageController::API) + run_action_method_name = controller.__register_action(action.to_sym) - handler = eval("->(env, params) { #{controller}.new(env, params).#{run_action_method_name} }") + meta[:controller] = $1 + meta[:action] = $2 + + handler = eval("->(env, params) { #{controller}.new(env, params).#{run_action_method_name} }") + else + # this is a Rails controller; notify `Rage::Router::Util::Cascade` to forward the request to Rails + handler = ->(_, _) { [404, { "X-Cascade" => "pass" }, []] } + end else raise "Non-string route handler should respond to `call`" unless handler.respond_to?(:call) # while regular handlers are expected to be called with the `env` and `params` objects, diff --git a/lib/rage/router/util.rb b/lib/rage/router/util.rb index 929d630e..9c9527b6 100644 --- a/lib/rage/router/util.rb +++ b/lib/rage/router/util.rb @@ -30,4 +30,19 @@ def path_to_name(str) end end end + + # @private + class Cascade + def initialize(rage_app, rails_app) + @rage_app = rage_app + @rails_app = rails_app + end + + def call(env) + result = @rage_app.call(env) + return result if result[0] == :__http_defer__ || result[1]["X-Cascade".freeze] != "pass".freeze + + @rails_app.call(env) + end + end end diff --git a/lib/rage/templates/config.ru b/lib/rage/templates/config.ru index 52de8a40..049a1ad5 100644 --- a/lib/rage/templates/config.ru +++ b/lib/rage/templates/config.ru @@ -1,4 +1,3 @@ require_relative "config/application" run Rage.application -Rage.load_middlewares(self) diff --git a/spec/integration/test_app/config.ru b/spec/integration/test_app/config.ru index 52de8a40..049a1ad5 100644 --- a/spec/integration/test_app/config.ru +++ b/spec/integration/test_app/config.ru @@ -1,4 +1,3 @@ require_relative "config/application" run Rage.application -Rage.load_middlewares(self) diff --git a/spec/rspec/config.ru b/spec/rspec/config.ru index f8774ed1..279ddd62 100644 --- a/spec/rspec/config.ru +++ b/spec/rspec/config.ru @@ -1,2 +1 @@ run Rage.application -Rage.load_middlewares(self)