Module: Grape::Throttling::Extension::Api::ClassMethods

Defined in:
lib/grape/throttling/extension/api.rb

Overview

:nodoc:

Instance Method Summary collapse

Instance Method Details

#use_throttle(max: 60, expire: 1.day, condition: proc { true }, identity: proc { request.ip }) ⇒ Object

rubocop:disable Style/ClassVars

Raises:



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/grape/throttling/extension/api.rb', line 11

def use_throttle(max: 60, expire: 1.day, condition: proc { true }, identity: proc { request.ip }) # rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
  max = max.try(:to_i).to_i
  raise ArgumentError, 'max must be positive number' unless max.positive?
  raise ArgumentError, 'condition must be Proc' unless condition.is_a?(Proc)
  raise ArgumentError, 'identity must be Proc' unless identity.is_a?(Proc)

  @@throttle = Counter.new(expire)
  @@throttle.define_singleton_method(:max) { max }
  @@throttle.define_singleton_method(:condition) { condition }
  @@throttle.define_singleton_method(:identity) { identity }

  helpers do
    def mixin_throttle_headers(count)
      header('X-RateLimit-Limit', @@throttle.max.to_s)
      header('X-Ratelimit-Used', count.to_s)
      header('X-RateLimit-Remaining', (@@throttle.max - count).to_s)
      header('X-RateLimit-Reset', (Time.now.utc + @@throttle.ttl(request.id_throttle)).to_s)

      header
    end
  end

  before do
    if instance_eval(&@@throttle.condition)
      request.enabled_throttle = true
      request.id_throttle = instance_eval(&@@throttle.identity)
      count = @@throttle.get(request.id_throttle)

      message = if respond_to?(Throttling.config.overspeed_message_method)
                  send(Throttling.config.overspeed_message_method)
                else
                  'API rate limit exceeded.'
                end

      error!(message, 403, mixin_throttle_headers(count)) if count >= @@throttle.max
    end
  end

  after { mixin_throttle_headers(@@throttle.incr(request.id_throttle)) if request.throttle? }

  @@throttle
end