class Rack::PooledThrottle::Throttle

Attributes

app[R]
options[R]

Public Class Methods

new(app, options = {}) click to toggle source
# File lib/rack/pooledthrottle/throttle.rb, line 6
def initialize(app, options = {})
  @app, @options = app, options
end

Public Instance Methods

call(env) click to toggle source
# File lib/rack/pooledthrottle/throttle.rb, line 10
def call(env)
  request = Rack::Request.new(env)
  allowed?(request) ? app.call(env) : rate_limit_exceeded(request)
end

Protected Instance Methods

allowed?(request) click to toggle source
# File lib/rack/pooledthrottle/throttle.rb, line 25
def allowed?(request)
  if throttled_request?(request)
    case
      when whitelisted?(request) then true
      when blacklisted?(request) then false
      else
        query_cache?(request)
    end
  else
    true
  end
end
blacklisted?(request) click to toggle source
# File lib/rack/pooledthrottle/throttle.rb, line 50
def blacklisted?(request)
  if bl = options[:blacklisted]
    bl.call(request)
  else
    false
  end
end
cache_key(request) click to toggle source
# File lib/rack/pooledthrottle/throttle.rb, line 58
def cache_key(request)
  "#{namespace}:#{key_prefix}#{client_identifier(request)}"
end
client_identifier(request) click to toggle source

@param [Rack::Request] request @return [String]

# File lib/rack/pooledthrottle/throttle.rb, line 66
def client_identifier(request)
  if cio = options[:client_identifier]
    cio.call(request)
  else
    request.ip.to_s
  end
end
http_error(code, message = nil, headers = {}) click to toggle source

Outputs an HTTP `4xx` or `5xx` response.

@param [Integer] code @param [String, to_s] message @param [Hash{String => String}] headers @return [Array(Integer, Hash, each)]

# File lib/rack/pooledthrottle/throttle.rb, line 111
def http_error(code, message = nil, headers = {})
  [code, {'Content-Type' => 'text/plain; charset=utf-8'}.merge(headers),
    [http_status(code), (message.nil? ? "\n" : " (#{message})\n")]]
end
http_status(code) click to toggle source

Returns the standard HTTP status message for the given status `code`.

@param [Integer] code @return [String]

# File lib/rack/pooledthrottle/throttle.rb, line 121
def http_status(code)
  [code, Rack::Utils::HTTP_STATUS_CODES[code]].join(' ')
end
key_prefix() click to toggle source
# File lib/rack/pooledthrottle/throttle.rb, line 78
def key_prefix
  options[:key_prefix]
end
max() click to toggle source
# File lib/rack/pooledthrottle/throttle.rb, line 86
def max
  (options[:max] || 10).to_i
end
namespace() click to toggle source
# File lib/rack/pooledthrottle/throttle.rb, line 74
def namespace
  options[:namespace] || 'rpt'
end
pool() click to toggle source
# File lib/rack/pooledthrottle/throttle.rb, line 82
def pool
  options[:pool]
end
query_cache?(request) click to toggle source
# File lib/rack/pooledthrottle/throttle.rb, line 38
def query_cache?(request)
  false
end
rate_limit_exceeded(request) click to toggle source

Outputs a `Rate Limit Exceeded` error.

@return [Array(Integer, Hash, each)]

# File lib/rack/pooledthrottle/throttle.rb, line 98
def rate_limit_exceeded(request)
  options[:rate_limit_exceeded_callback].call(request) if options[:rate_limit_exceeded_callback]
  headers = respond_to?(:retry_after) ? {'Retry-After' => retry_after.to_f.ceil.to_s} : {}
  http_error(options[:code] || 403, options[:message] || 'Rate Limit Exceeded', headers)
end
throttled_request?(request) click to toggle source
# File lib/rack/pooledthrottle/throttle.rb, line 17
def throttled_request?(request)
  if f = options[:throttled_request]
    f.call(request)
  else
    true
  end
end
ttl() click to toggle source
# File lib/rack/pooledthrottle/throttle.rb, line 90
def ttl
  (options[:ttl] || 60).to_i
end
whitelisted?(request) click to toggle source
# File lib/rack/pooledthrottle/throttle.rb, line 42
def whitelisted?(request)
  if wl = options[:whitelisted]
    wl.call(request)
  else
    false
  end
end