Class: Rack::Throttle::Limiter

Inherits:
Object
  • Object
show all
Defined in:
lib/rack/throttle/limiters/limiter.rb

Overview

This is the base class for rate limiter implementations.

Examples:

Defining a rate limiter subclass

class MyLimiter < Limiter
  def allowed?(request)
    # TODO: custom logic goes here
  end
end

Direct Known Subclasses

Interval, SlidingWindow, TimeWindow

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(app, options = {}) ⇒ Limiter

Returns a new instance of Limiter.

Parameters:

  • app (#call)
  • options (Hash{Symbol => Object}) (defaults to: {})

Options Hash (options):

  • :cache (String) — default: Hash.new
  • :key (String) — default: nil
  • :key_prefix (String) — default: nil
  • :code (Integer) — default: 403
  • :message (String) — default: "Rate Limit Exceeded"


23
24
25
26
27
28
29
30
# File 'lib/rack/throttle/limiters/limiter.rb', line 23

def initialize(app, options = {})
  rules = options.delete(:rules) || {}
  @app, @options, @matchers = app, options, []
  @matchers += Array(rules[:url]).map { |rule| UrlMatcher.new(rule) } if rules[:url]
  @matchers += Array(rules[:user_agent]).map { |rule| UserAgentMatcher.new(rule) } if rules[:user_agent]
  @matchers += Array(rules[:method]).map { |rule| MethodMatcher.new(rule) } if rules[:method]
  @matchers += Array(rules[:basic_auth]).map { |rule| BasicAuthMatcher.new(rule) } if rules[:basic_auth]
end

Instance Attribute Details

#appObject (readonly)

Returns the value of attribute app.



13
14
15
# File 'lib/rack/throttle/limiters/limiter.rb', line 13

def app
  @app
end

#matchersObject (readonly)

Returns the value of attribute matchers.



13
14
15
# File 'lib/rack/throttle/limiters/limiter.rb', line 13

def matchers
  @matchers
end

#optionsObject (readonly)

Returns the value of attribute options.



13
14
15
# File 'lib/rack/throttle/limiters/limiter.rb', line 13

def options
  @options
end

Instance Method Details

#allowed?(request) ⇒ Boolean

Returns ‘false` if the rate limit has been exceeded for the given `request`, or `true` otherwise.

Override this method in subclasses that implement custom rate limiter strategies.

Parameters:

  • request (Rack::Request)

Returns:

  • (Boolean)


68
69
70
71
72
73
74
# File 'lib/rack/throttle/limiters/limiter.rb', line 68

def allowed?(request)
  case
    when whitelisted?(request) then true
    when blacklisted?(request) then false
    else true # override in subclasses
  end
end

#blacklisted?(request) ⇒ Boolean

This method is abstract.

Returns ‘true` if the originator of the given `request` is blacklisted (not honoring rate limits, and thus permanently forbidden access without the need to maintain further rate limit counters).

The default implementation always returns ‘false`. Override this method in a subclass to implement custom blacklisting logic.

Parameters:

  • request (Rack::Request)

Returns:

  • (Boolean)


101
102
103
# File 'lib/rack/throttle/limiters/limiter.rb', line 101

def blacklisted?(request)
  false
end

#call(env) ⇒ Array(Integer, Hash, #each)

Parameters:

  • env (Hash{String => String})

Returns:

  • (Array(Integer, Hash, #each))

See Also:



36
37
38
39
40
41
42
43
44
45
# File 'lib/rack/throttle/limiters/limiter.rb', line 36

def call(env)
  request = Rack::Request.new(env)
  match_results = @matchers.map { |m| m.match?(request) }.uniq
  applicable = @matchers.empty? || match_results == [true]
  if applicable and !allowed?(request)
    rate_limit_exceeded
  else
    app.call(env)
  end
end

#restricted_url?(path) ⇒ Boolean

Returns ‘true` if no :url_rule regex or if the request path matches the :url regex, `false` otherwise.

You can override this class, though that might be weird.

Parameters:

  • path (String)

Returns:

  • (Boolean)


55
56
57
# File 'lib/rack/throttle/limiters/limiter.rb', line 55

def restricted_url?(path)
  options[:url_rule].nil? || options[:url_rule].match(path)
end

#whitelisted?(request) ⇒ Boolean

This method is abstract.

Returns ‘true` if the originator of the given `request` is whitelisted (not subject to further rate limits).

The default implementation always returns ‘false`. Override this method in a subclass to implement custom whitelisting logic.

Parameters:

  • request (Rack::Request)

Returns:

  • (Boolean)


86
87
88
# File 'lib/rack/throttle/limiters/limiter.rb', line 86

def whitelisted?(request)
  false
end