Class: Labkit::RateLimit::Identifier
- Inherits:
-
Object
- Object
- Labkit::RateLimit::Identifier
- Defined in:
- lib/labkit/rate_limit/identifier.rb
Overview
Identifier is a value object wrapping a hash of key-value pairs that describe the caller (e.g. user, ip, endpoint). Endpoint values are normalised at construction time (query string stripped).
Constant Summary collapse
- InvalidKeyError =
Class.new(ArgumentError)
- DuplicateNormalizedKeyError =
Class.new(InvalidKeyError)
Instance Attribute Summary collapse
-
#attributes ⇒ Object
readonly
Returns the value of attribute attributes.
Class Method Summary collapse
-
.normalize_endpoint(value) ⇒ Object
Normalize an endpoint value: strip query string.
Instance Method Summary collapse
- #==(other) ⇒ Object
-
#[](key) ⇒ Object
Return the value for a characteristic key.
-
#initialize(attributes = {}) ⇒ Identifier
constructor
A new instance of Identifier.
-
#to_h ⇒ Object
Serialize to a plain Hash suitable for JSON logging.
Constructor Details
#initialize(attributes = {}) ⇒ Identifier
Returns a new instance of Identifier.
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/labkit/rate_limit/identifier.rb', line 21 def initialize(attributes = {}) normalised = {} original_keys = {} attributes.each do |key, value| unless key.respond_to?(:to_sym) # Reject keys such as nil, 42, and [] instead of leaking NoMethodError; # identifiers must have a canonical symbol key for matching and serialization. raise InvalidKeyError, "Identifier key #{key.inspect} must respond to #to_sym" end normalised_key = key.to_sym if normalised.key?(normalised_key) # Reject { user: 1, "user" => 2 } (and its reverse order): silently # choosing a value would make the rate-limit bucket insertion-order dependent. raise DuplicateNormalizedKeyError, "Identifier keys normalize to the same key #{normalised_key.inspect}: " \ "#{original_keys[normalised_key].inspect} and #{key.inspect}" end original_keys[normalised_key] = key normalised[normalised_key] = value end normalised[:endpoint] = self.class.normalize_endpoint(normalised[:endpoint]) if normalised.key?(:endpoint) @attributes = normalised.freeze end |
Instance Attribute Details
#attributes ⇒ Object (readonly)
Returns the value of attribute attributes.
19 20 21 |
# File 'lib/labkit/rate_limit/identifier.rb', line 19 def attributes @attributes end |
Class Method Details
.normalize_endpoint(value) ⇒ Object
Normalize an endpoint value: strip query string.
13 14 15 16 17 |
# File 'lib/labkit/rate_limit/identifier.rb', line 13 def self.normalize_endpoint(value) return value unless value.is_a?(String) value.split("?", 2).first end |
Instance Method Details
#==(other) ⇒ Object
59 60 61 |
# File 'lib/labkit/rate_limit/identifier.rb', line 59 def ==(other) other.is_a?(Identifier) && other.attributes == @attributes end |
#[](key) ⇒ Object
Return the value for a characteristic key.
50 51 52 |
# File 'lib/labkit/rate_limit/identifier.rb', line 50 def [](key) @attributes[key.to_sym] end |
#to_h ⇒ Object
Serialize to a plain Hash suitable for JSON logging.
55 56 57 |
# File 'lib/labkit/rate_limit/identifier.rb', line 55 def to_h @attributes.transform_keys(&:to_s) end |