Class: ApiThrottling
- Inherits:
-
Object
- Object
- ApiThrottling
- Defined in:
- lib/api_throttling.rb
Instance Method Summary collapse
- #auth_required ⇒ Object
- #bad_request ⇒ Object
- #call(env, options = {}) ⇒ Object
- #generate_key(env, auth) ⇒ Object
-
#initialize(app, options = {}) ⇒ ApiThrottling
constructor
A new instance of ApiThrottling.
- #over_rate_limit ⇒ Object
Constructor Details
#initialize(app, options = {}) ⇒ ApiThrottling
Returns a new instance of ApiThrottling.
6 7 8 9 10 11 |
# File 'lib/api_throttling.rb', line 6 def initialize(app, ={}) @app = app = {:requests_per_hour => 60, :cache=>:redis, :auth=>true}.merge() @handler = Handlers.cache_handler_for([:cache]) raise "Sorry, we couldn't find a handler for the cache you specified: #{@options[:cache]}" unless @handler end |
Instance Method Details
#auth_required ⇒ Object
43 44 45 46 |
# File 'lib/api_throttling.rb', line 43 def auth_required body_text = "Authorization Required" [ 401, { 'Content-Type' => 'text/plain', 'Content-Length' => body_text.size.to_s }, [body_text] ] end |
#bad_request ⇒ Object
38 39 40 41 |
# File 'lib/api_throttling.rb', line 38 def bad_request body_text = "Bad Request" [ 400, { 'Content-Type' => 'text/plain', 'Content-Length' => body_text.size.to_s }, [body_text] ] end |
#call(env, options = {}) ⇒ Object
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
# File 'lib/api_throttling.rb', line 13 def call(env, ={}) if [:auth] auth = Rack::Auth::Basic::Request.new(env) return auth_required unless auth.provided? return bad_request unless auth.basic? end begin cache = @handler.new([:cache]) key = generate_key(env, auth) cache.increment(key) return over_rate_limit if cache.get(key).to_i > [:requests_per_hour] rescue Errno::ECONNREFUSED # If Redis-server is not running, instead of throwing an error, we simply do not throttle the API # It's better if your service is up and running but not throttling API, then to have it throw errors for all users # Make sure you monitor your redis-server so that it's never down. monit is a great tool for that. end @app.call(env) end |
#generate_key(env, auth) ⇒ Object
33 34 35 36 |
# File 'lib/api_throttling.rb', line 33 def generate_key(env, auth) return [:key].call(env, auth) if [:key] auth ? "#{auth.username}_#{Time.now.strftime("%Y-%m-%d-%H")}" : "#{Time.now.strftime("%Y-%m-%d-%H")}" end |
#over_rate_limit ⇒ Object
48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/api_throttling.rb', line 48 def over_rate_limit body_text = "Over Rate Limit" retry_after_in_seconds = (60 - Time.now.min) * 60 [ 503, { 'Content-Type' => 'text/plain', 'Content-Length' => body_text.size.to_s, 'Retry-After' => retry_after_in_seconds.to_s }, [body_text] ] end |