module Sinatra::RateLimiter::Helpers
Public Instance Methods
rate_limit(*args)
click to toggle source
# File lib/sinatra/rate-limiter.rb, line 13 def rate_limit(*args) return unless settings.rate_limiter and settings.rate_limiter_environments.include?(settings.environment) bucket, options, limits = parse_args(args) limiter = RateLimit.new(bucket, limits) limiter.settings = settings limiter.request = request limiter.options = options limiter.headers.each{|h,v| response.headers[h] = v} if limiter.options.send_headers if (error_locals = limiter.limits_exceeded?) response.headers['Retry-After'] = error_locals[:try_again] if limiter.options.send_headers request.env['sinatra.error.rate_limiter'] = Struct.new(*error_locals.keys).new(*error_locals.values) raise Sinatra::RateLimiter::Exceeded, "#{bucket.eql?('default') ? 'R' : bucket + ' r'}ate limit exceeded" end limiter.log_request end
Private Instance Methods
parse_args(args)
click to toggle source
# File lib/sinatra/rate-limiter.rb, line 37 def parse_args(args) bucket = (args.first.class == String) ? args.shift : 'default' options = (args.last.class == Hash) ? args.pop : {} limits = (args.size < 1) ? settings.rate_limiter_default_limits : args if (limits.size < 1) raise ArgumentError, 'No explicit or default limits values provided.' elsif (limits.map{|a| a.class}.select{|a| a != Fixnum}.count > 0) raise ArgumentError, 'Non-Fixnum parameters supplied. All parameters must be Fixnum except the first which may be a String.' elsif ((limits.map{|a| a.class}.size % 2) != 0) raise ArgumentError, 'Wrong number of Fixnum parameters supplied.' elsif !(bucket =~ /^[a-zA-Z0-9\-]*$/) raise ArgumentError, 'Limit name must be a String containing only a-z, A-Z, 0-9, and -.' end options.to_a.each do |option, value| case option when :send_headers raise ArgumentError, 'send_headers must be true or false' if !(value == (true or false)) when :header_prefix raise ArgumentError, 'header_prefix must be a String' if value.class != String when :identifier raise ArgumentError, 'identifier must be a Proc' if value.class != Proc else raise ArgumentError, "Invalid option #{option}" end end return [bucket, options, limits.each_slice(2).map{|a| {requests: a[0], seconds: a[1]}}] end