Class: Contrast::Framework::Sinatra::Support

Inherits:
Object
  • Object
show all
Extended by:
BaseSupport
Defined in:
lib/contrast/framework/sinatra/support.rb

Overview

Used when Sinatra is present to define framework specific behavior

Class Method Summary collapse

Methods included from BaseSupport

after_load_patches, application_name, before_load_patches!, collect_routes, current_route_coverage, detection_class, retrieve_request, server_type, streaming?, version

Class Method Details

.after_load_patchesObject

(See BaseSupport#after_load_patches)



109
110
111
112
113
114
115
116
117
118
119
# File 'lib/contrast/framework/sinatra/support.rb', line 109

def after_load_patches
  return unless defined?(::Sinatra)
  return unless Gem::Version.new(version) >= Gem::Version.new('3.0.0')

  Set.new([
            Contrast::Agent::Patching::Policy::AfterLoadPatch.new(
                'Rack::Protection::EncryptedCookie',
                'contrast/framework/sinatra/patch/encrypted_session_cookie',
                instrumenting_module: 'Contrast::Framework::Sinatra::Patch::EncryptedSessionCookie')
          ])
end

.application_nameObject



22
23
24
# File 'lib/contrast/framework/sinatra/support.rb', line 22

def application_name
  app_class&.cs__name
end

.application_rootObject



26
27
28
# File 'lib/contrast/framework/sinatra/support.rb', line 26

def application_root
  app_instance&.root
end

.collect_routesArray<Contrast::Agent::Reporting::DiscoveredRoute>

Find all classes that subclass ::Sinatra::Base. Gather their routes.



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/contrast/framework/sinatra/support.rb', line 51

def collect_routes
  return Contrast::Utils::ObjectShare::EMPTY_ARRAY unless defined?(::Sinatra) && defined?(::Sinatra::Base)

  routes = []
  sinatra_controllers.each do |controller|
    controller.routes.each_pair do |method, route_triplets|
      # Sinatra stores its routes as a triplet: [Mustermann::Sinatra, [], Proc]
      route_triplets.map(&:first).each do |route_pattern|
        routes << Contrast::Agent::Reporting::DiscoveredRoute.from_sinatra_route(controller, method,
                                                                                 route_pattern)
      end
    end
  end
  routes
end

.current_route_coverage(request, _controller = ::Sinatra::Base, full_route = nil) ⇒ Contrast::Agent::Reporting::RouteCoverage?

Returns the route coverage object or nil if no route.

Parameters:

  • request (Contrast::Agent::Request)

    a contrast tracked request.

  • _controller (::Sinatra::Base) (defaults to: ::Sinatra::Base)

    optionally use this controller instead of global ::Sinatra::Base.

Returns:



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/contrast/framework/sinatra/support.rb', line 72

def current_route_coverage request, _controller = ::Sinatra::Base, full_route = nil
  method = request.env[::Rack::REQUEST_METHOD] # GET, PUT, POST, etc...
  route = _cleaned_route(request)
  # Find route match--checking superclasses if necessary.
  sinatra_controllers.each do |potential_controller|
    next unless sinatra_controller?(potential_controller)

    next if potential_controller.nil? || potential_controller.cs__class == NilClass

    route_patterns = potential_controller.routes.fetch(method) { [] }.
        map(&:first)
    route_pattern = route_patterns.find do |matcher|
      matcher.params(route) # ::Mustermann::Sinatra match.
    end
    next unless route_pattern

    full_route ||= request.env[::Rack::PATH_INFO]
    new_route_coverage = Contrast::Agent::Reporting::RouteCoverage.new
    new_route_coverage.attach_rack_based_data(potential_controller, method, route_pattern, full_route)
    return new_route_coverage
  end
  nil
end

.detection_classObject



14
15
16
# File 'lib/contrast/framework/sinatra/support.rb', line 14

def detection_class
  'Sinatra'
end

.retrieve_request(env) ⇒ Object



104
105
106
# File 'lib/contrast/framework/sinatra/support.rb', line 104

def retrieve_request env
  ::Sinatra::Request.new(env)
end

.server_typeObject



30
31
32
# File 'lib/contrast/framework/sinatra/support.rb', line 30

def server_type
  'sinatra'
end

.sinatra_controller?(app) ⇒ Boolean

Given an object, determine if it is a Sinatra controller with routes.

Parameters:

  • app (Object)

    suspected Sinatra app.

Returns:

  • (Boolean)


38
39
40
41
42
43
44
45
46
# File 'lib/contrast/framework/sinatra/support.rb', line 38

def sinatra_controller? app
  # Sinatra is loaded?
  return false unless defined?(::Sinatra) && defined?(::Sinatra::Base)
  # App is a subclass of or actually is ::Sinatra::Base.
  return false unless (app.cs__respond_to?(:<) && app < ::Sinatra::Base) || app == ::Sinatra::Base

  # App has routes.
  !app.routes.empty?
end

.sinatra_controllersArray<Class<::Sinatra::Base>>

Search object space for sinatra controllers–any class that subclasses ::Sinatra::Base.

Returns:

  • (Array<Class<::Sinatra::Base>>)

    sinatra controlelrs



99
100
101
102
# File 'lib/contrast/framework/sinatra/support.rb', line 99

def sinatra_controllers
  @_sinatra_controllers ||=
    [::Sinatra::Base] + ObjectSpace.each_object(Class).select { |clazz| sinatra_controller?(clazz) }
end

.versionObject



18
19
20
# File 'lib/contrast/framework/sinatra/support.rb', line 18

def version
  ::Sinatra::VERSION
end