@@ -7,18 +7,16 @@ module Middleware
77 class Stack
88 extend Forwardable
99 class Middleware
10- extend Forwardable
11-
1210 attr_reader :args , :block , :klass
1311
14- def_delegators :klass , :name
15-
16- def initialize ( klass , *args , &block )
12+ def initialize ( klass , args , block )
1713 @klass = klass
1814 @args = args
1915 @block = block
2016 end
2117
18+ def name ; klass . name ; end # rubocop:disable Style/SingleLineMethods
19+
2220 def ==( other )
2321 case other
2422 when Middleware
@@ -32,7 +30,11 @@ def inspect
3230 klass . to_s
3331 end
3432
35- def use_in ( builder )
33+ def build ( builder )
34+ # we need to force the ruby2_keywords_hash for middlewares that initialize contains keywords
35+ # like ActionDispatch::RequestId since middleware arguments are serialized
36+ # https://rubyapi.org/3.4/o/hash#method-c-ruby2_keywords_hash
37+ args [ -1 ] = Hash . ruby2_keywords_hash ( args [ -1 ] ) if args . last . is_a? ( Hash ) && Hash . respond_to? ( :ruby2_keywords_hash )
3638 builder . use ( klass , *args , &block )
3739 end
3840 end
@@ -48,51 +50,50 @@ def initialize
4850 @others = [ ]
4951 end
5052
51- def insert ( index , *args , &block )
53+ def insert ( index , klass , *args , &block )
5254 index = assert_index ( index , :before )
53- middleware = self . class ::Middleware . new ( *args , &block )
54- middlewares . insert ( index , middleware )
55+ middlewares . insert ( index , self . class ::Middleware . new ( klass , args , block ) )
5556 end
56- ruby2_keywords :insert if respond_to? ( :ruby2_keywords , true )
5757
5858 alias insert_before insert
5959
6060 def insert_after ( index , *args , &block )
6161 index = assert_index ( index , :after )
6262 insert ( index + 1 , *args , &block )
6363 end
64- ruby2_keywords :insert_after if respond_to? ( :ruby2_keywords , true )
6564
66- def use ( ... )
67- middleware = self . class ::Middleware . new ( ... )
65+ def use ( klass , * args , & block )
66+ middleware = self . class ::Middleware . new ( klass , args , block )
6867 middlewares . push ( middleware )
6968 end
7069
7170 def merge_with ( middleware_specs )
72- middleware_specs . each do |operation , *args |
71+ middleware_specs . each do |operation , klass , *args |
7372 if args . last . is_a? ( Proc )
7473 last_proc = args . pop
75- public_send ( operation , *args , &last_proc )
74+ public_send ( operation , klass , *args , &last_proc )
7675 else
77- public_send ( operation , *args )
76+ public_send ( operation , klass , *args )
7877 end
7978 end
8079 end
8180
8281 # @return [Rack::Builder] the builder object with our middlewares applied
83- def build ( builder = Rack ::Builder . new )
84- others . shift ( others . size ) . each { |m | merge_with ( m ) }
85- middlewares . each do |m |
86- m . use_in ( builder )
82+ def build
83+ Rack ::Builder . new . tap do |builder |
84+ others . shift ( others . size ) . each { |m | merge_with ( m ) }
85+ middlewares . each do |m |
86+ m . build ( builder )
87+ end
8788 end
88- builder
8989 end
9090
9191 # @description Add middlewares with :use operation to the stack. Store others with :insert_* operation for later
9292 # @param [Array] other_specs An array of middleware specifications (e.g. [[:use, klass], [:insert_before, *args]])
9393 def concat ( other_specs )
94- @others << Array ( other_specs ) . reject { |o | o . first == :use }
95- merge_with ( Array ( other_specs ) . select { |o | o . first == :use } )
94+ use , not_use = other_specs . partition { |o | o . first == :use }
95+ others << not_use
96+ merge_with ( use )
9697 end
9798
9899 protected
0 commit comments