Class: Contrast::Agent::Request
Overview
This class is the Contrast representation of the Rack::Request object. It provides access to the original Rack::Request object as well as extracts data in a format that the Agent expects, caching those transformations in order to avoid repeatedly creating Strings & thrashing GC.
Constant Summary collapse
- INNER_REST_TOKEN =
%r{/\d+/}.cs__freeze
- LAST_REST_TOKEN =
%r{/\d+$}.cs__freeze
- INNER_NUMBER_MARKER =
'/{n}/'
- LAST_NUMBER_MARKER =
'/{n}'
- STATIC_SUFFIXES =
/\.(?:js|css|jpeg|jpg|gif|png|ico|woff|svg|pdf|eot|ttf|jar)$/i.cs__freeze
- MEDIA_TYPE_MARKERS =
%w[image/ text/css text/javascript].cs__freeze
Instance Attribute Summary collapse
-
#rack_request ⇒ Object
readonly
Returns the value of attribute rack_request.
Instance Method Summary collapse
- #body ⇒ Object
- #document_type ⇒ Object
-
#dtm ⇒ Contrast::Api::Dtm::HttpRequest
Unlike most of our translation, which is called where needed for each message and forgotten, we’ll leave this method to call the build as we don’t want to pay to reconstruct the DTM for this Request multiple times.
- #file_names ⇒ Object
- #hash_id ⇒ Object
-
#headers ⇒ Object
Header keys upcased and any underscores replaced with dashes.
-
#initialize(rack_request) ⇒ Request
constructor
A new instance of Request.
-
#normalized_uri ⇒ Object
Returns a normalized form of the URI.
- #parameters ⇒ Object
-
#static? ⇒ Boolean
Utility method for checking if a request is for a static resource.
Methods included from Components::Interface
Constructor Details
#initialize(rack_request) ⇒ Request
Returns a new instance of Request.
34 35 36 |
# File 'lib/contrast/agent/request.rb', line 34 def initialize rack_request @rack_request = rack_request end |
Instance Attribute Details
#rack_request ⇒ Object (readonly)
Returns the value of attribute rack_request.
29 30 31 |
# File 'lib/contrast/agent/request.rb', line 29 def rack_request @rack_request end |
Instance Method Details
#body ⇒ Object
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/contrast/agent/request.rb', line 87 def body # Memoize a flag indicating whether we've tried to read the body or not # (can't use body because it might be nil) @_body_read ||= begin body = rack_request.body if defined?(Rack::Multipart) && defined?(Rack::Multipart::UploadedFile) && body.is_a?(Rack::Multipart::UploadedFile) logger.trace("not parsing uploaded file body :: #{ body.original_filename }::#{ body.content_type }") @_body = nil else logger.trace("parsing body from request :: #{ body.cs__class.cs__name }") @_body = Contrast::Utils::StringUtils.force_utf8(read_body(body)) end true end # Return memoized body (which might be nil) @_body end |
#document_type ⇒ Object
57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/contrast/agent/request.rb', line 57 def document_type @_document_type ||= begin if /xml/i.match?(content_type) || body&.start_with?('<?xml') :XML elsif /json/i.match?(content_type) || body&.match?(/\s*[{\[]/) :JSON else :NORMAL end end end |
#dtm ⇒ Contrast::Api::Dtm::HttpRequest
Unlike most of our translation, which is called where needed for each message and forgotten, we’ll leave this method to call the build as we don’t want to pay to reconstruct the DTM for this Request multiple times.
114 115 116 |
# File 'lib/contrast/agent/request.rb', line 114 def dtm @_dtm ||= Contrast::Api::Dtm::HttpRequest.build(self) end |
#file_names ⇒ Object
122 123 124 125 126 127 128 129 130 131 |
# File 'lib/contrast/agent/request.rb', line 122 def file_names @_file_names ||= begin names = {} parsed_data = Rack::Multipart.parse_multipart(rack_request.env) traverse_parsed_multipart(parsed_data, names) rescue StandardError => _e logger.warn('Unable to parse multipart request!') {} end end |
#hash_id ⇒ Object
133 134 135 |
# File 'lib/contrast/agent/request.rb', line 133 def hash_id @_hash_id ||= Contrast::Utils::HashDigest.generate_request_hash(self) end |
#headers ⇒ Object
Header keys upcased and any underscores replaced with dashes
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/contrast/agent/request.rb', line 70 def headers @_headers ||= begin with_contrast_scope do hash = {} env.each do |key, value| next unless key name = key.to_s next unless name.start_with?(Contrast::Utils::ObjectShare::HTTP_SCORE) hash[Contrast::Utils::StringUtils.normalized_key(name)] = value end hash end end end |
#normalized_uri ⇒ Object
Returns a normalized form of the URI. In “normal” URIs this will return an unchanged String, but in REST-y URIs this will normalize the digit path tokens, e.g.:
/accounts/5/view …becomes: /accounts/n/view
Should also handle the ;jsessionid.
47 48 49 50 51 52 53 54 55 |
# File 'lib/contrast/agent/request.rb', line 47 def normalized_uri @_normalized_uri ||= begin path = rack_request.path uri = path.split(Contrast::Utils::ObjectShare::SEMICOLON)[0] # remove ;jsessionid uri = uri.split(Contrast::Utils::ObjectShare::QUESTION_MARK)[0] # remove ?query_string= uri.gsub(INNER_REST_TOKEN, INNER_NUMBER_MARKER) # replace interior tokens uri.gsub(LAST_REST_TOKEN, LAST_NUMBER_MARKER) # replace last token end end |
#parameters ⇒ Object
118 119 120 |
# File 'lib/contrast/agent/request.rb', line 118 def parameters @_parameters ||= with_contrast_scope { normalize_params(rack_request.params) } end |
#static? ⇒ Boolean
Utility method for checking if a request is for a static resource.
142 143 144 145 146 147 148 149 150 |
# File 'lib/contrast/agent/request.rb', line 142 def static? return true if normalized_uri&.match?(STATIC_SUFFIXES) accepts = Array(headers['ACCEPT'])&.first&.to_s return false unless accepts return false if accepts.start_with?('*/*') accepts.start_with?(*MEDIA_TYPE_MARKERS) end |