lib/contrast/agent/middleware.rb in contrast-agent-4.2.0 vs lib/contrast/agent/middleware.rb in contrast-agent-4.3.0
- old
+ new
@@ -77,11 +77,11 @@
# to the user up the Rack framework.
def call env
Contrast::Utils::HeapDumpUtil.run
if AGENT.enabled?
- Contrast::Agent::StaticAnalysis.catchup
+ handle_first_request
call_with_agent(env)
else
app.call(env)
end
end
@@ -89,20 +89,51 @@
private
def setup_agent
SETTINGS.reset_state
+ inform_deprecations
+
if CONFIG.invalid?
AGENT.disable!
logger.error('!!! CONFIG FILE IS INVALID - DISABLING CONTRAST AGENT !!!')
elsif AGENT.disabled?
logger.warn('Contrast disabled by configuration. Continuing without instrumentation.')
else
AGENT.enable!
end
end
+ # Some things have to wait until first request to happen, either because
+ # resolution is not complete or because the framework will preload
+ # classes, which confuses some of our instrumentation.
+ def handle_first_request
+ @_handle_first_request ||= begin
+ Contrast::Agent::StaticAnalysis.catchup
+ force_patching
+ true
+ end
+ end
+
+ # TODO: RUBY-1090 remove this method and those it calls.
+ #
+ # These modules are auto-loaded by Rails, meaning they are defined at
+ # startup, but that they don't actually exist. We account for this in
+ # most cases by using the ClassUtil.truly_defined? method, but it appears
+ # to fail for these Modules. In the short term, we can forcing a re-patch
+ # so that their dead zones apply.
+ def force_patching
+ force_patch(ActionDispatch::FileHandler) if defined?(ActionDispatch::FileHandler)
+ force_patch(ActionDispatch::Http::MimeNegotiation) if defined?(ActionDispatch::Http::MimeNegotiation)
+ force_patch(ActionView::Template) if defined?(ActionView::Template)
+ end
+
+ def force_patch mod
+ data = Contrast::Agent::ModuleData.new(mod)
+ Contrast::Agent::Patching::Policy::Patcher.send(:patch_into_module, data, true)
+ end
+
# This is where we process each request we intercept as a middleware. We make the request context
# available globally so that it can be accessed from anywhere. A RequestHandler object is made
# for each request, which handles prefilter and postfilter operations.
def call_with_agent env
Contrast::Agent.thread_watcher.ensure_running?
@@ -170,9 +201,27 @@
[exception_control[:status], {}, [exception_control[:message]]]
else
logger.debug('Re-throwing original error', exception)
raise exception
end
+ end
+
+ # As we deprecate support to prepare to remove dead code, we need to
+ # inform our users still relying on the now deprecated and soon to be
+ # removed functionality. This method handles doing that by leveraging the
+ # standard Kernel#warn approach
+ def inform_deprecations
+ # Ruby 2.5 is currently in security maintenance, meaning int is only
+ # receiving updates for security issues. It will move to eol on 31
+ # March 2021. As such, we can remove support for it in Q2. We'll begin
+ # the deprecation warnings now so that customers have time to reach out
+ # if they'll be impacted.
+ # TODO: RUBY-715 remove this part of the method, leaving it empty if
+ # there are no other deprecations, when we drop 2.5 support.
+ return unless RUBY_VERSION < '2.6.0'
+
+ Kernel.warn('[Contrast Security] [DEPRECATION] Support for Ruby 2.5 will be removed in April 2021. '\
+ 'Please contact Customer Support prior if you require continued support.')
end
end
end
end