module Rollbar::RequestDataExtractor

Constants

ALLOWED_BODY_PARSEABLE_METHODS
ALLOWED_HEADERS_REGEX

Public Instance Methods

extract_person_data_from_controller(env) click to toggle source
# File lib/rollbar/request_data_extractor.rb, line 16
def extract_person_data_from_controller(env)
  if env.key?('rollbar.person_data')
    person_data = env['rollbar.person_data'] || {}
  else
    controller = env['action_controller.instance']
    person_data = begin
      controller.rollbar_person_data
    rescue StandardError
      {}
    end
  end

  person_data
end
extract_request_data_from_rack(env) click to toggle source
# File lib/rollbar/request_data_extractor.rb, line 31
def extract_request_data_from_rack(env)
  rack_req = ::Rack::Request.new(env)
  sensitive_params = sensitive_params_list(env)

  get_params = scrub_params(rollbar_get_params(rack_req), sensitive_params)
  post_params = scrub_params(rollbar_post_params(rack_req), sensitive_params)
  raw_body_params = scrub_params(mergeable_raw_body_params(rack_req),
                                 sensitive_params)
  cookies = scrub_params(rollbar_request_cookies(rack_req), sensitive_params)
  session = scrub_params(rollbar_request_session(env), sensitive_params)
  route_params = scrub_params(rollbar_route_params(env), sensitive_params)

  url = scrub_url(rollbar_url(env), sensitive_params)

  data = {
    :url => url,
    :params => route_params,
    :GET => get_params,
    :POST => post_params,
    :body => Rollbar::JSON.dump(raw_body_params),
    :user_ip => rollbar_user_ip(env),
    :headers => rollbar_headers(env),
    :cookies => cookies,
    :session => session,
    :method => rollbar_request_method(env)
  }

  if env['action_dispatch.request_id']
    data[:request_id] =
      env['action_dispatch.request_id']
  end

  data
end
scrub_params(params, sensitive_params) click to toggle source
# File lib/rollbar/request_data_extractor.rb, line 79
def scrub_params(params, sensitive_params)
  options = {
    :params => params,
    :config => Rollbar.configuration.scrub_fields,
    :extra_fields => sensitive_params,
    :whitelist => Rollbar.configuration.scrub_whitelist
  }
  Rollbar::Scrubbers::Params.call(options)
end
scrub_url(url, sensitive_params) click to toggle source
# File lib/rollbar/request_data_extractor.rb, line 66
def scrub_url(url, sensitive_params)
  options = {
    :url => url,
    :scrub_fields => Array(Rollbar.configuration.scrub_fields) + sensitive_params,
    :scrub_user => Rollbar.configuration.scrub_user,
    :scrub_password => Rollbar.configuration.scrub_password,
    :randomize_scrub_length => Rollbar.configuration.randomize_scrub_length,
    :whitelist => Rollbar.configuration.scrub_whitelist
  }

  Rollbar::Scrubbers::URL.call(options)
end

Private Instance Methods

find_not_private_ip(ips) click to toggle source
# File lib/rollbar/request_data_extractor.rb, line 187
def find_not_private_ip(ips)
  ips.detect do |ip|
    octets = ip.match(/^(\d{1,3}).(\d{1,3}).(\d{1,3}).(\d{1,3})$/)[1, 4].map(&:to_i)

    is_private = (octets[0] == 10) ||
                 ((octets[0] == 172) && (octets[1] >= 16) && (octets[1] <= 31)) ||
                 ((octets[0] == 192) && (octets[1] == 168))

    !is_private
  end
end
json_request?(rack_req) click to toggle source
# File lib/rollbar/request_data_extractor.rb, line 236
def json_request?(rack_req)
  json_regex = /\bjson\b/

  !!(rack_req.env['CONTENT_TYPE'] =~ json_regex)
end
mergeable_raw_body_params(rack_req) click to toggle source
# File lib/rollbar/request_data_extractor.rb, line 91
def mergeable_raw_body_params(rack_req)
  raw_body_params = rollbar_raw_body_params(rack_req)

  case raw_body_params
  when Hash
    raw_body_params
  when Array
    { 'body.multi' => raw_body_params }
  else
    { 'body.value' => raw_body_params }
  end
end
read_raw_body(body) click to toggle source
# File lib/rollbar/request_data_extractor.rb, line 227
def read_raw_body(body)
  return {} unless body.respond_to?(:rewind)

  body.rewind
  raw_body = body.read
  body.rewind
  raw_body
end
rollbar_get_params(rack_req) click to toggle source
# File lib/rollbar/request_data_extractor.rb, line 199
def rollbar_get_params(rack_req)
  rack_req.GET
rescue StandardError
  {}
end
rollbar_headers(env) click to toggle source
# File lib/rollbar/request_data_extractor.rb, line 108
def rollbar_headers(env)
  env.keys.grep(ALLOWED_HEADERS_REGEX).map do |header|
    name = header.gsub(/^HTTP_/, '').split('_').map(&:capitalize).join('-')
    if name == 'Cookie'
      {}
    elsif sensitive_headers_list.include?(name)
      { name => Rollbar::Scrubbers.scrub_value(env[header]) }
    elsif name == 'X-Forwarded-For' && !Rollbar.configuration.collect_user_ip
      {}
    elsif name == 'X-Forwarded-For' &&
          Rollbar.configuration.collect_user_ip &&
          Rollbar.configuration.anonymize_user_ip
      ips = env[header].sub(' ', '').split(',')
      ips = ips.map { |ip| Rollbar::Util::IPAnonymizer.anonymize_ip(ip) }
      { name => ips.join(', ') }
    elsif name == 'X-Real-Ip' && !Rollbar.configuration.collect_user_ip
      {}
    elsif name == 'X-Real-Ip' &&
          Rollbar.configuration.collect_user_ip &&
          Rollbar.configuration.anonymize_user_ip
      { name => Rollbar::Util::IPAnonymizer.anonymize_ip(env[header]) }
    else
      { name => env[header] }
    end
  end.inject(:merge)
end
rollbar_post_params(rack_req) click to toggle source
# File lib/rollbar/request_data_extractor.rb, line 205
def rollbar_post_params(rack_req)
  rack_req.POST
rescue StandardError
  {}
end
rollbar_raw_body_params(rack_req) click to toggle source
# File lib/rollbar/request_data_extractor.rb, line 211
def rollbar_raw_body_params(rack_req)
  correct_method = ALLOWED_BODY_PARSEABLE_METHODS.include?(rack_req.request_method)

  return {} unless correct_method
  return {} unless json_request?(rack_req)

  raw_body = read_raw_body(rack_req.body)
  begin
    Rollbar::JSON.load(raw_body)
  rescue StandardError
    raw_body
  end
rescue StandardError
  {}
end
rollbar_request_cookies(rack_req) click to toggle source
# File lib/rollbar/request_data_extractor.rb, line 265
def rollbar_request_cookies(rack_req)
  rack_req.cookies
rescue StandardError
  {}
end
rollbar_request_method(env) click to toggle source
# File lib/rollbar/request_data_extractor.rb, line 104
def rollbar_request_method(env)
  env['REQUEST_METHOD'] || env[:method]
end
rollbar_request_session(env) click to toggle source
# File lib/rollbar/request_data_extractor.rb, line 257
def rollbar_request_session(env)
  session = env.fetch('rack.session', {})

  session.to_hash
rescue StandardError
  {}
end
rollbar_route_params(env) click to toggle source
# File lib/rollbar/request_data_extractor.rb, line 242
def rollbar_route_params(env)
  return {} unless defined?(Rails)

  begin
    environment = { :method => rollbar_request_method(env) }

    # recognize_path() will return the controller, action
    # route params (if any)and format (if defined)
    ::Rails.application.routes.recognize_path(env['PATH_INFO'],
                                              environment)
  rescue StandardError
    {}
  end
end
rollbar_url(env) click to toggle source
# File lib/rollbar/request_data_extractor.rb, line 135
def rollbar_url(env)
  forwarded_proto = env['HTTP_X_FORWARDED_PROTO'] || env['rack.url_scheme'] || ''
  scheme = forwarded_proto.split(',').first

  host = env['HTTP_X_FORWARDED_HOST'] || env['HTTP_HOST'] || env['SERVER_NAME'] || ''
  host = host.split(',').first.strip unless host.empty?

  path = env['ORIGINAL_FULLPATH'] || env['REQUEST_URI']
  query = env['QUERY_STRING'].to_s.empty? ? nil : "?#{env['QUERY_STRING']}"
  path ||= "#{env['SCRIPT_NAME']}#{env['PATH_INFO']}#{query}"
  path = "/#{path}" if !(path.nil? || path.empty?) && (path.to_s.slice(0, 1) != '/')

  port = env['HTTP_X_FORWARDED_PORT']
  if port && !(!scheme.nil? && scheme.casecmp('http').zero? && port.to_i == 80) && \
     !(!scheme.nil? && scheme.casecmp('https').zero? && port.to_i == 443) && \
     !(host.include? ':')
    host = "#{host}:#{port}"
  end

  [scheme, '://', host, path].join
end
rollbar_user_ip(env) click to toggle source
# File lib/rollbar/request_data_extractor.rb, line 157
def rollbar_user_ip(env)
  return nil unless Rollbar.configuration.collect_user_ip

  user_ip_string = (user_ip_at_configured_key(env) ||
                    env['action_dispatch.remote_ip'] ||
                    env['HTTP_X_REAL_IP'] ||
                    x_forwarded_for_client(env['HTTP_X_FORWARDED_FOR']) ||
                    env['REMOTE_ADDR']).to_s

  user_ip_string = Rollbar::Util::IPAnonymizer.anonymize_ip(user_ip_string)

  Rollbar::Util::IPObfuscator.obfuscate_ip(user_ip_string)
rescue StandardError
  nil
end
sensitive_headers_list() click to toggle source
# File lib/rollbar/request_data_extractor.rb, line 275
def sensitive_headers_list
  unless Rollbar.configuration.scrub_headers &&
         Rollbar.configuration.scrub_headers.is_a?(Array)
    return []
  end

  # Normalize into the expected matching format
  Rollbar.configuration.scrub_headers.map do |header|
    header.split(/[-_]/).map(&:capitalize).join('-').gsub(/^Http-/, '')
  end
end
sensitive_params_list(env) click to toggle source
# File lib/rollbar/request_data_extractor.rb, line 271
def sensitive_params_list(env)
  Array(env['action_dispatch.parameter_filter'])
end
user_ip_at_configured_key(env) click to toggle source
# File lib/rollbar/request_data_extractor.rb, line 173
def user_ip_at_configured_key(env)
  return nil unless Rollbar.configuration.user_ip_rack_env_key

  env[Rollbar.configuration.user_ip_rack_env_key]
end
x_forwarded_for_client(header_value) click to toggle source
# File lib/rollbar/request_data_extractor.rb, line 179
def x_forwarded_for_client(header_value)
  return nil unless header_value

  ips = header_value.split(',').map(&:strip)

  find_not_private_ip(ips)
end