Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
unreleased
----------

Feature:
- Add `redis_prefix` configuration to provide a custom prefix to Redis ratelimit
keys.

v2.4.1
------

Expand Down Expand Up @@ -30,10 +34,7 @@ Feature:

```rb
GraphAttack.configure do |config|
# config.threshold = 15
# config.interval = 60
# config.on = :ip
# config.redis_client = Redis.new
end
```

Expand Down
15 changes: 14 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ class QueryType < GraphQL::Schema::Object
end
```

This would allow 15 requests per minute by the same IP address, blocking the 16th and subsequent requests within that 60-second window.
This would allow 15 requests per minute by the same IP address, blocking the
16th and subsequent requests within that 60-second window.

## Requirements

Expand Down Expand Up @@ -85,6 +86,17 @@ extension GraphAttack::RateLimit,
redis_client: Redis.new(url: "…")
```

### Custom Redis ratelimit key prefix

Use a custom prefix in front of the Redis ratelimit key:

```rb
extension GraphAttack::RateLimit,
threshold: 15,
interval: 60,
redis_prefix: "my-app/production/"
```

### Common configuration

To have a default configuration for all rate-limited fields, you can create an
Expand All @@ -96,6 +108,7 @@ GraphAttack.configure do |config|
# config.interval = 60
# config.on = :ip
# config.redis_client = Redis.new
# config.redis_prefix = ""
end
```

Expand Down
4 changes: 4 additions & 0 deletions lib/graph_attack/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,15 @@ class Configuration
# Use a custom Redis client.
attr_accessor :redis_client

# Prefix for all rate limit Redis keys.
attr_accessor :redis_prefix

def initialize
@threshold = nil
@interval = nil
@on = :ip
@redis_client = Redis.new
@redis_prefix = ""
end
end

Expand Down
28 changes: 18 additions & 10 deletions lib/graph_attack/rate_limit.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,28 @@ def resolve(object:, arguments:, **_rest)

private

def key
suffix = "-#{on}" if on != :ip

"graphql-query-#{field.name}#{suffix}"
end

def calls_exceeded_on_query?(rate_limited_field)
def calls_exceeded_on_query?(field)
with_redis_client do |redis_client|
rate_limit = Ratelimit.new(rate_limited_field, redis: redis_client)
if rate_limit.exceeded?(key, threshold: threshold, interval: interval)
limit = Ratelimit.new(rate_limit_key_name(field), redis: redis_client)
if limit.exceeded?(key, threshold: threshold, interval: interval)
true
else
rate_limit.add(key)
limit.add(key)
false
end
end
end

def key
suffix = "-#{on}" if on != :ip

"graphql-query-#{field.name}#{suffix}"
end

def rate_limit_key_name(field)
"#{redis_prefix}#{field}"
end

def threshold
options[:threshold] ||
GraphAttack.configuration.threshold ||
Expand Down Expand Up @@ -66,5 +70,9 @@ def with_redis_client(&block)
def on
options[:on] || GraphAttack.configuration.on
end

def redis_prefix
options[:redis_prefix] || GraphAttack.configuration.redis_prefix
end
end
end
Loading