aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_dispatch/middleware/stack.rb
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack/lib/action_dispatch/middleware/stack.rb')
-rw-r--r--actionpack/lib/action_dispatch/middleware/stack.rb116
1 files changed, 116 insertions, 0 deletions
diff --git a/actionpack/lib/action_dispatch/middleware/stack.rb b/actionpack/lib/action_dispatch/middleware/stack.rb
new file mode 100644
index 0000000000..b82f8aa3a3
--- /dev/null
+++ b/actionpack/lib/action_dispatch/middleware/stack.rb
@@ -0,0 +1,116 @@
+# frozen_string_literal: true
+
+require "active_support/inflector/methods"
+require "active_support/dependencies"
+
+module ActionDispatch
+ class MiddlewareStack
+ class Middleware
+ attr_reader :args, :block, :klass
+
+ def initialize(klass, args, block)
+ @klass = klass
+ @args = args
+ @block = block
+ end
+
+ def name; klass.name; end
+
+ def ==(middleware)
+ case middleware
+ when Middleware
+ klass == middleware.klass
+ when Class
+ klass == middleware
+ end
+ end
+
+ def inspect
+ if klass.is_a?(Class)
+ klass.to_s
+ else
+ klass.class.to_s
+ end
+ end
+
+ def build(app)
+ klass.new(app, *args, &block)
+ end
+ end
+
+ include Enumerable
+
+ attr_accessor :middlewares
+
+ def initialize(*args)
+ @middlewares = []
+ yield(self) if block_given?
+ end
+
+ def each
+ @middlewares.each { |x| yield x }
+ end
+
+ def size
+ middlewares.size
+ end
+
+ def last
+ middlewares.last
+ end
+
+ def [](i)
+ middlewares[i]
+ end
+
+ def unshift(klass, *args, &block)
+ middlewares.unshift(build_middleware(klass, args, block))
+ end
+
+ def initialize_copy(other)
+ self.middlewares = other.middlewares.dup
+ end
+
+ def insert(index, klass, *args, &block)
+ index = assert_index(index, :before)
+ middlewares.insert(index, build_middleware(klass, args, block))
+ end
+
+ alias_method :insert_before, :insert
+
+ def insert_after(index, *args, &block)
+ index = assert_index(index, :after)
+ insert(index + 1, *args, &block)
+ end
+
+ def swap(target, *args, &block)
+ index = assert_index(target, :before)
+ insert(index, *args, &block)
+ middlewares.delete_at(index + 1)
+ end
+
+ def delete(target)
+ middlewares.delete_if { |m| m.klass == target }
+ end
+
+ def use(klass, *args, &block)
+ middlewares.push(build_middleware(klass, args, block))
+ end
+
+ def build(app = Proc.new)
+ middlewares.freeze.reverse.inject(app) { |a, e| e.build(a) }
+ end
+
+ private
+
+ def assert_index(index, where)
+ i = index.is_a?(Integer) ? index : middlewares.index { |m| m.klass == index }
+ raise "No such middleware to insert #{where}: #{index.inspect}" unless i
+ i
+ end
+
+ def build_middleware(klass, args, block)
+ Middleware.new(klass, args, block)
+ end
+ end
+end