class Rollbar::Scrubbers::URL

Constants

SCRUB_ALL

Public Class Methods

call(*args) click to toggle source
# File lib/rollbar/scrubbers/url.rb, line 11
def self.call(*args)
  new.call(*args)
end

Public Instance Methods

call(options = {}) click to toggle source
# File lib/rollbar/scrubbers/url.rb, line 15
def call(options = {})
  url = ascii_encode(options[:url])

  filter(url,
         build_regex(options[:scrub_fields]),
         options[:scrub_user],
         options[:scrub_password],
         options.fetch(:randomize_scrub_length, true),
         options[:scrub_fields].include?(SCRUB_ALL),
         build_whitelist_regex(options[:whitelist] || []))
rescue StandardError => e
  message = '[Rollbar] There was an error scrubbing the url: ' \
    "#{e}, options: #{options.inspect}"
  Rollbar.logger.error(message)
  url
end

Private Instance Methods

ascii_encode(url) click to toggle source
# File lib/rollbar/scrubbers/url.rb, line 34
def ascii_encode(url)
  # In some cases non-ascii characters won't be properly encoded, so we do it here.
  #
  # The standard encoders (the CGI and URI methods) are not reliable when
  # the query string is already embedded in the full URL, but the inconsistencies
  # are limited to issues with characters in the ascii range. (For example,
  # the '#' if it appears in an unexpected place.) For escaping non-ascii,
  # they are all OK, so we'll take care to skip the ascii chars.

  return url if url.ascii_only?

  # Iterate each char and only escape non-ascii characters.
  url.each_char.map { |c| c.ascii_only? ? c : CGI.escape(c) }.join
end
build_regex(fields) click to toggle source

Builds a regex to match with any of the received fields. The built regex will also match array params like 'user_ids[]'.

# File lib/rollbar/scrubbers/url.rb, line 71
def build_regex(fields)
  fields_or = fields.map { |field| "#{field}(\\[\\])?" }.join('|')

  Regexp.new("^#{fields_or}$")
end
build_whitelist_regex(whitelist) click to toggle source
# File lib/rollbar/scrubbers/url.rb, line 49
def build_whitelist_regex(whitelist)
  fields = whitelist.find_all { |f| f.is_a?(String) || f.is_a?(Symbol) }
  return unless fields.any?

  Regexp.new(fields.map { |val| /\A#{Regexp.escape(val.to_s)}\z/ }.join('|'))
end
decode_www_form(query) click to toggle source
# File lib/rollbar/scrubbers/url.rb, line 99
def decode_www_form(query)
  URI.decode_www_form(query)
end
encode_www_form(params) click to toggle source
# File lib/rollbar/scrubbers/url.rb, line 103
def encode_www_form(params)
  restore_square_brackets(URI.encode_www_form(params))
end
filter(url, regex, scrub_user, scrub_password, randomize_scrub_length, scrub_all, whitelist) click to toggle source
# File lib/rollbar/scrubbers/url.rb, line 56
def filter(url, regex, scrub_user, scrub_password, randomize_scrub_length,
           scrub_all, whitelist)
  uri = URI.parse(url)

  uri.user = filter_user(uri.user, scrub_user, randomize_scrub_length)
  uri.password = filter_password(uri.password, scrub_password,
                                 randomize_scrub_length)
  uri.query = filter_query(uri.query, regex, randomize_scrub_length, scrub_all,
                           whitelist)

  uri.to_s
end
filter_key?(key, regex, scrub_all, whitelist) click to toggle source
# File lib/rollbar/scrubbers/url.rb, line 129
def filter_key?(key, regex, scrub_all, whitelist)
  !(whitelist === key) && (scrub_all || regex === key)
end
filter_password(password, scrub_password, randomize_scrub_length) click to toggle source
# File lib/rollbar/scrubbers/url.rb, line 81
def filter_password(password, scrub_password, randomize_scrub_length)
  if scrub_password && password
    filtered_value(password,
                   randomize_scrub_length)
  else
    password
  end
end
filter_query(query, regex, randomize_scrub_length, scrub_all, whitelist) click to toggle source
# File lib/rollbar/scrubbers/url.rb, line 90
def filter_query(query, regex, randomize_scrub_length, scrub_all, whitelist)
  return query unless query

  params = decode_www_form(query)

  encode_www_form(filter_query_params(params, regex, randomize_scrub_length,
                                      scrub_all, whitelist))
end
filter_query_params(params, regex, randomize_scrub_length, scrub_all, whitelist) click to toggle source
# File lib/rollbar/scrubbers/url.rb, line 116
def filter_query_params(params, regex, randomize_scrub_length, scrub_all,
                        whitelist)
  params.map do |key, value|
    [key,
     if filter_key?(key, regex, scrub_all,
                    whitelist)
       filtered_value(value, randomize_scrub_length)
     else
       value
     end]
  end
end
filter_user(user, scrub_user, randomize_scrub_length) click to toggle source
# File lib/rollbar/scrubbers/url.rb, line 77
def filter_user(user, scrub_user, randomize_scrub_length)
  scrub_user && user ? filtered_value(user, randomize_scrub_length) : user
end
filtered_value(value, randomize_scrub_length) click to toggle source
# File lib/rollbar/scrubbers/url.rb, line 133
def filtered_value(value, randomize_scrub_length)
  if randomize_scrub_length
    random_filtered_value
  else
    '*' * (begin
      value.length
    rescue StandardError
      8
    end)
  end
end
random_filtered_value() click to toggle source
# File lib/rollbar/scrubbers/url.rb, line 145
def random_filtered_value
  '*' * rand(3..7)
end
restore_square_brackets(query) click to toggle source
# File lib/rollbar/scrubbers/url.rb, line 107
def restore_square_brackets(query)
  # We want this to rebuild array params like foo[]=1&foo[]=2
  #
  # URI.encode_www_form follows the spec at
  # https://url.spec.whatwg.org/#concept-urlencoded-serializer
  # and percent encodes square brackets. Here we change them back.
  query.gsub('%5B', '[').gsub('%5D', ']')
end