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['"][^>]*>/
STACKIFY_SETTING_TAG =
'<script type="text/javascript">(window.StackifySettings ||'

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.



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

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



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
# File 'lib/stackify_apm/response_manipulator.rb', line 44

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

  transaction_id = defined?(StackifyRubyAPM.current_transaction.id) ? StackifyRubyAPM.current_transaction.id : nil
  inject_flag = false

  if transaction_id
    inject_flag = true
  else
    info 'RUM Injection Error: No Transaction ID found.'
  end

  return unless inject_flag

  return if has_stackify_tag(source[0..SCAN_LIMIT])

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

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

#close_old_response(response) ⇒ Object



95
96
97
# File 'lib/stackify_apm/response_manipulator.rb', line 95

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



76
77
78
79
# File 'lib/stackify_apm/response_manipulator.rb', line 76

def find_end_of_head_open(beginning_of_source)
  head_open = beginning_of_source.index(HEAD_START)
  beginning_of_source.index(GT, head_open) + 1 if head_open
end

#gather_source(response) ⇒ Object



85
86
87
88
89
90
91
92
93
# File 'lib/stackify_apm/response_manipulator.rb', line 85

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

#has_stackify_tag(beginning_of_source) ⇒ Object



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

def has_stackify_tag(beginning_of_source)
  !!beginning_of_source.index(STACKIFY_SETTING_TAG)
end

#rebuild_rack_responseObject



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

def rebuild_rack_response
  [rack_status, rack_headers, rack_body]
end