class Honeybadger::Util::Sanitizer
Sanitizer
sanitizes data for sending to Honeybadger’s API. The filters are based on Rails’ HTTP
parameter filter.
Constants
- BASIC_OBJECT
- COOKIE_PAIRS
- COOKIE_PAIR_SEP
- COOKIE_SEP
- DEPTH
- ENCODE_OPTS
- FILTERED
- IMMUTABLE
- MAX_STRING_SIZE
- RAISED
- RECURSION
- TRUNCATED
- VALID_ENCODINGS
Attributes
Public Class Methods
Source
# File lib/honeybadger/util/sanitizer.rb, line 34 def initialize(max_depth: 20, filters: []) @filters = !filters.empty? @max_depth = max_depth strings, @regexps, @blocks = [], [], [] filters.each do |item| case item when Proc @blocks << item when Regexp @regexps << item else strings << Regexp.escape(item.to_s) end end @deep_regexps, @regexps = @regexps.partition { |r| r.to_s.include?('\\.'.freeze) } deep_strings, @strings = strings.partition { |s| s.include?('\\.'.freeze) } @regexps << Regexp.new(strings.join('|'.freeze), true) unless strings.empty? @deep_regexps << Regexp.new(deep_strings.join('|'.freeze), true) unless deep_strings.empty? end
Source
# File lib/honeybadger/util/sanitizer.rb, line 29 def self.sanitize(data) @sanitizer ||= new @sanitizer.sanitize(data) end
Public Instance Methods
Source
# File lib/honeybadger/util/sanitizer.rb, line 146 def filter_url(url) return url unless filters? filtered_url = url.to_s.dup filtered_url.scan(/(?:^|&|\?)([^=?&]+)=([^&]+)/).each do |m| next unless filter_key?(m[0]) filtered_url.gsub!(/#{Regexp.escape(m[1])}/, FILTERED) end filtered_url end
Source
# File lib/honeybadger/util/sanitizer.rb, line 58 def sanitize(data, depth = 0, stack = nil, parents = []) return BASIC_OBJECT if basic_object?(data) if recursive?(data) return RECURSION if stack && stack.include?(data.object_id) stack = stack ? stack.dup : Set.new stack << data.object_id end case data when Hash return DEPTH if depth >= max_depth hash = data.to_hash new_hash = {} hash.each_pair do |key, value| parents.push(key) if deep_regexps key = key.kind_of?(Symbol) ? key : sanitize(key, depth+1, stack, parents) if filter_key?(key, parents) new_hash[key] = FILTERED else value = sanitize(value, depth+1, stack, parents) if blocks.any? && !recursive?(value) key = key.dup if can_dup?(key) value = value.dup if can_dup?(value) blocks.each { |b| b.call(key, value) } end new_hash[key] = value end parents.pop if deep_regexps end new_hash when Array, Set return DEPTH if depth >= max_depth data.to_a.map do |value| sanitize(value, depth+1, stack, parents) end when Numeric, TrueClass, FalseClass, NilClass data when String sanitize_string(data) when -> (d) { d.respond_to?(:to_honeybadger) } return DEPTH if depth >= max_depth begin data = data.to_honeybadger rescue return RAISED end sanitize(data, depth+1, stack, parents) else # all other objects klass = data.class begin data = String(data) rescue return RAISED end return "#<#{klass.name}>" if inspected?(data) sanitize_string(data) end end
Private Instance Methods
Source
# File lib/honeybadger/util/sanitizer.rb, line 196 def basic_object?(object) object.respond_to?(:to_s) false rescue # BasicObject doesn't respond to `#respond_to?`. true end
Source
# File lib/honeybadger/util/sanitizer.rb, line 204 def can_dup?(obj) !IMMUTABLE.any? {|k| obj.kind_of?(k) } end
Source
# File lib/honeybadger/util/sanitizer.rb, line 167 def filter_key?(key, parents = nil) return false unless filters? return true if key.respond_to?(:=~) && regexps.any? { |r| key =~ r } return true if deep_regexps && parents && (joined = parents.join(".")) && deep_regexps.any? { |r| joined =~ r } false end
Source
# File lib/honeybadger/util/sanitizer.rb, line 208 def inspected?(string) String(string) =~ /#<.*>/ end
Source
# File lib/honeybadger/util/sanitizer.rb, line 192 def recursive?(data) data.is_a?(Hash) || data.is_a?(Array) || data.is_a?(Set) || data.respond_to?(:to_honeybadger) end
Source
# File lib/honeybadger/util/sanitizer.rb, line 174 def sanitize_string(string) string = valid_encoding(string) return string unless string.respond_to?(:size) && string.size > MAX_STRING_SIZE string[0...MAX_STRING_SIZE] + TRUNCATED end
Source
# File lib/honeybadger/util/sanitizer.rb, line 187 def valid_encoding(string) return string if valid_encoding?(string) string.encode(Encoding::UTF_8, **ENCODE_OPTS) end
Source
# File lib/honeybadger/util/sanitizer.rb, line 180 def valid_encoding?(string) string.valid_encoding? && ( VALID_ENCODINGS.include?(string.encoding) || VALID_ENCODINGS.include?(Encoding.compatible?(''.freeze, string)) ) end