Class: Contrast::Framework::Grape::Support

Inherits:
Object
  • Object
show all
Extended by:
Components::Logger::InstanceMethods, BaseSupport
Defined in:
lib/contrast/framework/grape/support.rb

Overview

Used when Grape is present to define framework specific behaviour

Class Method Summary collapse

Methods included from Components::Logger::InstanceMethods

cef_logger, logger

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

.application_nameObject



23
24
25
# File 'lib/contrast/framework/grape/support.rb', line 23

def application_name
  app_class&.cs__name
end

.application_rootObject



27
28
29
# File 'lib/contrast/framework/grape/support.rb', line 27

def application_root
  app_instance&.root
end

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

Find all classes that subclass ::Grape::API, Gather their routes



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/contrast/framework/grape/support.rb', line 53

def collect_routes
  return Contrast::Utils::ObjectShare::EMPTY_ARRAY unless grape_defined?

  # Each Grape controller has endpoints and each endpoints has routes
  # and that's why we need to go through each one and create separate RouteCoverage object
  routes = []
  grape_controllers.each do |c|
    c&.endpoints&.each do |endpoint|
      endpoint&.routes&.map do |r|
        pattern = r.pattern.pattern
        routes << Contrast::Agent::Reporting::DiscoveredRoute.from_grape_controller(c, r.request_method,
                                                                                    pattern, r.path)
      end
    end
  end
  routes
end

.current_route_coverage(request, controller = ::Grape::API, 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 (::Grape::API) (defaults to: ::Grape::API)

    optionally use this controller instead of global ::Grape::API.

Returns:



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

def current_route_coverage request, controller = ::Grape::API, full_route = nil
  return unless grape_controller?(controller)

  method = request.env[::Rack::REQUEST_METHOD] # GET, PUT, POST, etc...

  # Find final controller - actually we gotta match the route to the scanned application
  # Initially Grape compiles all routes on startup, so we can use the url from the request
  # and create the observed route
  # Class < Grape::API, Grape::Router::Route
  final_controller, route_pattern = _route_recurse(method, _cleaned_route(request), grape_controllers)
  return unless final_controller

  full_route ||= request.env[::Rack::PATH_INFO]

  new_route_coverage = Contrast::Agent::Reporting::RouteCoverage.new
  new_route_coverage.attach_rack_based_data(final_controller, method, route_pattern, full_route)
  new_route_coverage
end

.detection_classObject



15
16
17
# File 'lib/contrast/framework/grape/support.rb', line 15

def detection_class
  'Grape::API'
end

.grape_controller?(app) ⇒ Boolean

Given an object, determine if it is a Grape controller. Which could include cases of ::Grape::API subclass or actual class

Parameters:

  • app (Object)

    suspected Grape app.

Returns:

  • (Boolean)


40
41
42
43
44
45
46
47
48
# File 'lib/contrast/framework/grape/support.rb', line 40

def grape_controller? app
  # Grape is loaded?
  return false unless grape_defined?

  # App is a subclass of or actually is ::Grape::API.
  return false unless app.cs__respond_to?(:<=) && app <= ::Grape::API

  true
end

.grape_controllersArray<::Grape::API>

Search object space for grape controllers–any class that subclasses ::Grape::API.

Returns:

  • (Array<::Grape::API>)

    grape controllers



98
99
100
# File 'lib/contrast/framework/grape/support.rb', line 98

def grape_controllers
  ObjectSpace.each_object(Class).select { |klass| klass < ::Grape::API }
end

.retrieve_request(env) ⇒ Object

Grape Request inherits the same as the Sinatra, so we can easily call it as it’s called in Sinatra



103
104
105
# File 'lib/contrast/framework/grape/support.rb', line 103

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

.server_typeObject



31
32
33
# File 'lib/contrast/framework/grape/support.rb', line 31

def server_type
  'grape'
end

.versionObject



19
20
21
# File 'lib/contrast/framework/grape/support.rb', line 19

def version
  ::Grape::VERSION
end