@@ -7,18 +7,18 @@ module Middleware
7
7
class Stack
8
8
extend Forwardable
9
9
class Middleware
10
- extend Forwardable
11
-
12
10
attr_reader :args , :block , :klass
13
11
14
- def_delegators :klass , :name
15
-
16
- def initialize ( klass , *args , &block )
12
+ def initialize ( klass , args , block )
17
13
@klass = klass
18
14
@args = args
19
15
@block = block
20
16
end
21
17
18
+ def name
19
+ klass . name
20
+ end
21
+
22
22
def ==( other )
23
23
case other
24
24
when Middleware
@@ -32,7 +32,11 @@ def inspect
32
32
klass . to_s
33
33
end
34
34
35
- def use_in ( builder )
35
+ def build ( builder )
36
+ # we need to force the ruby2_keywords_hash for middlewares that initialize contains keywords
37
+ # like ActionDispatch::RequestId since middleware arguments are serialized
38
+ # https://rubyapi.org/3.4/o/hash#method-c-ruby2_keywords_hash
39
+ args [ -1 ] = Hash . ruby2_keywords_hash ( args [ -1 ] ) if args . last . is_a? ( Hash ) && Hash . respond_to? ( :ruby2_keywords_hash )
36
40
builder . use ( klass , *args , &block )
37
41
end
38
42
end
@@ -48,51 +52,50 @@ def initialize
48
52
@others = [ ]
49
53
end
50
54
51
- def insert ( index , *args , &block )
55
+ def insert ( index , klass , *args , &block )
52
56
index = assert_index ( index , :before )
53
- middleware = self . class ::Middleware . new ( *args , &block )
54
- middlewares . insert ( index , middleware )
57
+ middlewares . insert ( index , self . class ::Middleware . new ( klass , args , block ) )
55
58
end
56
- ruby2_keywords :insert if respond_to? ( :ruby2_keywords , true )
57
59
58
60
alias insert_before insert
59
61
60
62
def insert_after ( index , *args , &block )
61
63
index = assert_index ( index , :after )
62
64
insert ( index + 1 , *args , &block )
63
65
end
64
- ruby2_keywords :insert_after if respond_to? ( :ruby2_keywords , true )
65
66
66
- def use ( ... )
67
- middleware = self . class ::Middleware . new ( ... )
67
+ def use ( klass , * args , & block )
68
+ middleware = self . class ::Middleware . new ( klass , args , block )
68
69
middlewares . push ( middleware )
69
70
end
70
71
71
72
def merge_with ( middleware_specs )
72
- middleware_specs . each do |operation , *args |
73
+ middleware_specs . each do |operation , klass , *args |
73
74
if args . last . is_a? ( Proc )
74
75
last_proc = args . pop
75
- public_send ( operation , *args , &last_proc )
76
+ public_send ( operation , klass , *args , &last_proc )
76
77
else
77
- public_send ( operation , *args )
78
+ public_send ( operation , klass , *args )
78
79
end
79
80
end
80
81
end
81
82
82
83
# @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 )
84
+ def build
85
+ Rack ::Builder . new . tap do |builder |
86
+ others . shift ( others . size ) . each { |m | merge_with ( m ) }
87
+ middlewares . each do |m |
88
+ m . build ( builder )
89
+ end
87
90
end
88
- builder
89
91
end
90
92
91
93
# @description Add middlewares with :use operation to the stack. Store others with :insert_* operation for later
92
94
# @param [Array] other_specs An array of middleware specifications (e.g. [[:use, klass], [:insert_before, *args]])
93
95
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 } )
96
+ use , not_use = other_specs . partition { |o | o . first == :use }
97
+ others << not_use
98
+ merge_with ( use )
96
99
end
97
100
98
101
protected
0 commit comments