Class: StackifyRubyAPM::ResponseManipulator

Inherits:
Object
  • Object
show all
Includes:
Log
Defined in:
lib/stackify_apm/response_manipulator.rb

Overview

an abstraction for manipulating the HTML we capture in the middleware

Constant Summary collapse

SCAN_LIMIT =

examine in order to look for a RUM insertion point.

50_000
HEAD_START =
'<head'.freeze
HEAD_END =
'</head'.freeze
RUM_SCRIPT_VARIABLE =
'[RUM_SCRIPT_VARIABLE'.freeze
BRKT =
']'.freeze
GT =
'>'.freeze
CHARSET_RE =
/<\s*meta[^>]+charset\s*=[^>]*>/
X_UA_COMPATIBLE_RE =
/<\s*meta[^>]+http-equiv\s*=\s*['"]x-ua-compatible['"][^>]*>/

Constants included from Log

Log::PREFIX

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Log

#debug, #error, #fatal, #info, #log, #warn

Constructor Details

#initialize(env, rack_response, config) ⇒ ResponseManipulator

Returns a new instance of ResponseManipulator.



26
27
28
29
30
31
32
33
34
35
# File 'lib/stackify_apm/response_manipulator.rb', line 26

def initialize(env, rack_response, config)
  @env = env
  @rack_response = rack_response

  @rack_status = rack_response[0]
  @rack_headers = rack_response[1]
  @rack_body = rack_response[2]
  @rack_flagger = nil
  @config = config
end

Instance Attribute Details

#envObject (readonly)

Returns the value of attribute env.



14
15
16
# File 'lib/stackify_apm/response_manipulator.rb', line 14

def env
  @env
end

#jsfile_to_injectObject (readonly)

Returns the value of attribute jsfile_to_inject.



12
13
14
# File 'lib/stackify_apm/response_manipulator.rb', line 12

def jsfile_to_inject
  @jsfile_to_inject
end

#rack_bodyObject (readonly)

Returns the value of attribute rack_body.



13
14
15
# File 'lib/stackify_apm/response_manipulator.rb', line 13

def rack_body
  @rack_body
end

#Rack_flaggerObject (readonly)

Returns the value of attribute Rack_flagger.



13
14
15
# File 'lib/stackify_apm/response_manipulator.rb', line 13

def Rack_flagger
  @Rack_flagger
end

#rack_headersObject (readonly)

Returns the value of attribute rack_headers.



13
14
15
# File 'lib/stackify_apm/response_manipulator.rb', line 13

def rack_headers
  @rack_headers
end

#rack_responseObject (readonly)

Returns the value of attribute rack_response.



12
13
14
# File 'lib/stackify_apm/response_manipulator.rb', line 12

def rack_response
  @rack_response
end

#rack_statusObject (readonly)

Returns the value of attribute rack_status.



13
14
15
# File 'lib/stackify_apm/response_manipulator.rb', line 13

def rack_status
  @rack_status
end

Instance Method Details

#adjust_pagehtml_responseObject

rubocop:disable Metrics/CyclomaticComplexity rubocop:disable Metrics/PerceivedComplexity



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/stackify_apm/response_manipulator.rb', line 43

def adjust_pagehtml_response
  response = @rack_body
  source = gather_source(response)
  close_old_response(response)
  return nil unless source

  client_id = @config.client_id
  device_id = @config.device_id
  client_rundomain = @config.client_run_domain
  inject_flag = false

  if client_id && device_id
    if StackifyRubyAPM.check_isdomain(client_rundomain)
      inject_flag = true
    else
      info 'RUM Injection Error: Client RUM Domain is invalid.'
    end
  else
    info 'RUM Injection Error: No Device ID and/or Client ID found.'
  end

  return unless inject_flag

  # Only scan the first 50k (roughly) then give up.
  insertion_index = find_end_of_head_open(source[0..SCAN_LIMIT])

  if insertion_index && inject_flag
    source = source[0...insertion_index] <<
             StackifyRubyAPM.inject_rum_script <<
             source[insertion_index..-1]
  end
  source
end

#close_old_response(response) ⇒ Object



90
91
92
# File 'lib/stackify_apm/response_manipulator.rb', line 90

def close_old_response(response)
  response.close if response.respond_to?(:close)
end

#find_end_of_head_open(beginning_of_source) ⇒ Object

rubocop:enable Metrics/CyclomaticComplexity rubocop:enable Metrics/PerceivedComplexity



79
80
81
82
# File 'lib/stackify_apm/response_manipulator.rb', line 79

def find_end_of_head_open(beginning_of_source)
  head_open = beginning_of_source.index(HEAD_END)
  beginning_of_source.index(GT, head_open) - 6 if head_open
end

#gather_source(response) ⇒ Object



84
85
86
87
88
# File 'lib/stackify_apm/response_manipulator.rb', line 84

def gather_source(response)
  source = nil
  response.each { |fragment| source ? (source << fragment.to_s) : (source = fragment.to_s) }
  source
end

#rebuild_rack_responseObject



37
38
39
# File 'lib/stackify_apm/response_manipulator.rb', line 37

def rebuild_rack_response
  [rack_status, rack_headers, rack_body]
end