class Galago::RateLimiter

Constants

X_LIMIT_HEADER
X_REMAINING_HEADER
X_RESET_HEADER

Public Class Methods

configure() { |instance| ... } click to toggle source
# File lib/galago/rate_limiter.rb, line 13
def self.configure
  yield Configuration.instance
end
new(app) click to toggle source
# File lib/galago/rate_limiter.rb, line 17
def initialize(app)
  @app = app
  @config = Configuration.instance
  @counter = @config.counter
end

Public Instance Methods

call(env) click to toggle source
# 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

Private Instance Methods

execute_callback(api_key) click to toggle source
# File lib/galago/rate_limiter.rb, line 49
def execute_callback(api_key)
  @config.callback.call(api_key)
end
expires_in() click to toggle source
# File lib/galago/rate_limiter.rb, line 61
def expires_in
  timestamp % 3600
end
limit_exceeded?(throughput) click to toggle source
# File lib/galago/rate_limiter.rb, line 53
def limit_exceeded?(throughput)
  throughput > @config.limit
end
limit_resets_at() click to toggle source

Reset at the beginning of every hour.

# File lib/galago/rate_limiter.rb, line 66
def limit_resets_at
  timestamp - (timestamp % 3600) + 3600
end
timestamp() click to toggle source
# File lib/galago/rate_limiter.rb, line 57
def timestamp
  @timestamp ||= Time.now.utc.to_i
end