posthog-rails 3.13.0 → 3.13.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. checksums.yaml +4 -4
  2. data/lib/posthog/rails/railtie.rb +121 -8
  3. metadata +1 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dbadf59825cbf2d519a1eab2aa36e56cba2bc9c395076857e50bc126e41300b0
4
- data.tar.gz: de897b215980ee6bcbbfe54416073fed3d5b9321fce30443dacb015a7785b073
3
+ metadata.gz: bc1787c8bae17ac624fd59a956284a92e996082c0774a83e27cf8b7554ae5393
4
+ data.tar.gz: d13ef6ae2d87f8820050f4fd86e9588b09d5cfea1591548d9a70a0b0d38810d3
5
5
  SHA512:
6
- metadata.gz: 33068f5f9b2673d0f9acf9f1acb20f50a8f99c04e1182911d9245c539e8d2566a3c42fb6da125d89853a7cadadf187754b3d49e24666a46d274800bc9badf82f
7
- data.tar.gz: d94d7cff285e97a7769683f1349689b770d8ddb3610ceb0f21cf68067ca56b0fe2ffbb103f2c5720fd39270cc3d84f6c8fb9e9c4e39fb83e2fb65a8da35123c3
6
+ metadata.gz: 8cf28fe0b562b377d411bc259c3f72a8e0ea9a28051714f2fa933f8082c1a58e1fa1f24f58759413fb4d0f1ad83b684ba74930183836da1f5c3e3bacfe07842d
7
+ data.tar.gz: 897e312969d310aaf1559bd5e9c02f9684faaa755375dc2f1dc36759d35db7f1a8766981474ecb5c13e431cb1e0ed34d265e42762c41f54f2ce99ee169ec3313
@@ -64,24 +64,137 @@ module PostHog
64
64
  end
65
65
  end
66
66
 
67
+ MISSING_MIDDLEWARE_MESSAGE = 'No such middleware to insert'
68
+ MIDDLEWARE_FALLBACK_OPERATION = :posthog_insert_middleware_with_fallback
69
+
70
+ module MiddlewareStackFallback
71
+ def posthog_insert_middleware_with_fallback(location, target, middleware)
72
+ PostHog::Rails::Railtie.instance.send(
73
+ :insert_middleware_with_fallback,
74
+ self,
75
+ location,
76
+ target,
77
+ middleware
78
+ )
79
+ end
80
+
81
+ private :posthog_insert_middleware_with_fallback
82
+ end
83
+
84
+ private_constant :MISSING_MIDDLEWARE_MESSAGE,
85
+ :MIDDLEWARE_FALLBACK_OPERATION,
86
+ :MiddlewareStackFallback
87
+
67
88
  # @api private
68
89
  # @return [void]
69
90
  def insert_middleware_after(app, target, middleware)
70
- # During initialization, app.config.middleware is a MiddlewareStackProxy
71
- # which only supports recording operations (insert_after, use, etc.)
72
- # and does NOT support query methods like include?.
73
- app.config.middleware.insert_after(target, middleware)
91
+ insert_middleware(app.config.middleware, :after, target, middleware)
74
92
  end
75
93
 
76
94
  # @api private
77
95
  # @return [void]
78
96
  def insert_middleware_before(app, target, middleware)
79
- # During initialization, app.config.middleware is a MiddlewareStackProxy
80
- # which only supports recording operations (insert_before, use, etc.)
81
- # and does NOT support query methods like include?.
82
- app.config.middleware.insert_before(target, middleware)
97
+ insert_middleware(app.config.middleware, :before, target, middleware)
98
+ end
99
+
100
+ # During initialization, app.config.middleware is usually a
101
+ # Rails::Configuration::MiddlewareStackProxy. The proxy only records
102
+ # operations, so missing-target errors happen later when Rails builds the
103
+ # real ActionDispatch::MiddlewareStack. Add our own deferred operation so
104
+ # we can fall back at build time instead of crashing or silently skipping.
105
+ def insert_middleware(middleware_stack, location, target, middleware)
106
+ if middleware_stack_proxy?(middleware_stack)
107
+ append_middleware_operation(middleware_stack, location, target, middleware)
108
+ else
109
+ insert_middleware_with_fallback(middleware_stack, location, target, middleware)
110
+ end
83
111
  end
84
112
 
113
+ def middleware_stack_proxy?(middleware_stack)
114
+ defined?(::Rails::Configuration::MiddlewareStackProxy) &&
115
+ middleware_stack.instance_of?(::Rails::Configuration::MiddlewareStackProxy) &&
116
+ middleware_stack.instance_variable_defined?(:@operations)
117
+ end
118
+
119
+ def append_middleware_operation(middleware_stack, location, target, middleware)
120
+ operations = middleware_stack.instance_variable_get(:@operations)
121
+
122
+ if callable_middleware_operations?(middleware_stack, operations)
123
+ operations << lambda do |resolved_stack|
124
+ insert_middleware_with_fallback(resolved_stack, location, target, middleware)
125
+ end
126
+ else
127
+ ensure_middleware_stack_fallback_operation!
128
+ operations << [MIDDLEWARE_FALLBACK_OPERATION, [location, target, middleware], nil]
129
+ end
130
+ end
131
+
132
+ def callable_middleware_operations?(middleware_stack, operations)
133
+ operation = operations.first || probe_middleware_operation(middleware_stack)
134
+
135
+ operation.respond_to?(:call)
136
+ end
137
+
138
+ def probe_middleware_operation(middleware_stack)
139
+ probe = middleware_stack.class.new
140
+ probe.use(Object)
141
+ probe.instance_variable_get(:@operations).first
142
+ end
143
+
144
+ def ensure_middleware_stack_fallback_operation!
145
+ require 'action_dispatch/middleware/stack' unless defined?(::ActionDispatch::MiddlewareStack)
146
+ return if ::ActionDispatch::MiddlewareStack < MiddlewareStackFallback
147
+
148
+ ::ActionDispatch::MiddlewareStack.include(MiddlewareStackFallback)
149
+ end
150
+
151
+ def insert_middleware_with_fallback(middleware_stack, location, target, middleware)
152
+ perform_middleware_insert(middleware_stack, location, target, middleware)
153
+ rescue RuntimeError => e
154
+ raise unless missing_middleware_error?(e)
155
+
156
+ fallback_insert_middleware(middleware_stack, location, target, middleware)
157
+ end
158
+
159
+ def perform_middleware_insert(middleware_stack, location, target, middleware)
160
+ if location == :after
161
+ middleware_stack.insert_after(target, middleware)
162
+ else
163
+ middleware_stack.insert_before(target, middleware)
164
+ end
165
+ end
166
+
167
+ def fallback_insert_middleware(middleware_stack, location, target, middleware)
168
+ fallback_position = if location == :before && middleware_stack.respond_to?(:unshift)
169
+ middleware_stack.unshift(middleware)
170
+ 'beginning'
171
+ else
172
+ middleware_stack.use(middleware)
173
+ 'end'
174
+ end
175
+
176
+ PostHog::Logging.logger.warn(
177
+ "Could not find #{target.inspect} in the Rails middleware stack; " \
178
+ "inserted #{middleware.inspect} at the #{fallback_position} " \
179
+ 'of the stack instead.'
180
+ )
181
+ end
182
+
183
+ def missing_middleware_error?(error)
184
+ error.message.start_with?(MISSING_MIDDLEWARE_MESSAGE)
185
+ end
186
+
187
+ private :insert_middleware,
188
+ :middleware_stack_proxy?,
189
+ :append_middleware_operation,
190
+ :callable_middleware_operations?,
191
+ :probe_middleware_operation,
192
+ :ensure_middleware_stack_fallback_operation!,
193
+ :insert_middleware_with_fallback,
194
+ :perform_middleware_insert,
195
+ :fallback_insert_middleware,
196
+ :missing_middleware_error?
197
+
85
198
  # Build the PostHog Logs pipeline and broadcast Rails.logger into it.
86
199
  #
87
200
  # @api private
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: posthog-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.13.0
4
+ version: 3.13.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - PostHog