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