Class: Galago::RateLimiter

Inherits:
Object
  • Object
show all
Defined in:
lib/galago/rate_limiter.rb,
lib/galago/rate_limiter/configuration.rb,
lib/galago/rate_limiter/redis_counter.rb,
lib/galago/rate_limiter/memcached_counter.rb

Defined Under Namespace

Classes: Configuration, MemcachedCounter, Railtie, RedisCounter

Constant Summary collapse

X_LIMIT_HEADER =
'X-RateLimit-Limit'.freeze
X_RESET_HEADER =
'X-RateLimit-Reset'.freeze
X_REMAINING_HEADER =
'X-RateLimit-Remaining'.freeze

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(app) ⇒ RateLimiter

Returns a new instance of RateLimiter.



17
18
19
20
21
# File 'lib/galago/rate_limiter.rb', line 17

def initialize(app)
  @app = app
  @config = Configuration.instance
  @counter = @config.counter
end

Class Method Details

.configure {|Configuration.instance| ... } ⇒ Object

Yields:



13
14
15
# File 'lib/galago/rate_limiter.rb', line 13

def self.configure
  yield Configuration.instance
end

Instance Method Details

#call(env) ⇒ Object



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/galago/rate_limiter.rb', line 23

def call(env)
  api_key = env[@config.api_key_header]
  return @app.call(env) if api_key.nil?
  throughput = @counter.increment(api_key, 1, expires_in: expires_in)

  if limit_exceeded?(throughput)
    execute_callback(api_key)
    status = 403
    headers = {
      X_LIMIT_HEADER => @config.limit.to_s,
      X_REMAINING_HEADER => "0",
      X_RESET_HEADER => limit_resets_at.to_s
    }
    body = [JSON(message: "API rate limit exceeded for #{api_key}")]
  else
    status, headers, body = @app.call(env)
    headers[X_LIMIT_HEADER] = @config.limit.to_s
    headers[X_REMAINING_HEADER] = (@config.limit - throughput).to_s
    headers[X_RESET_HEADER] = limit_resets_at.to_s
  end

  [status, headers, body]
end