Skip to content

Commit

Permalink
Add documentation to Rate Limiter
Browse files Browse the repository at this point in the history
  • Loading branch information
gabrielpra1 committed Feb 17, 2020
1 parent 1db3ea9 commit f0de163
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 1 deletion.
50 changes: 50 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ It provides the following middlewares:
- [Object Authorization](#object-authorization)
- [Object Scope Authorization](#object-scope-authorization)
- [Field Authorization](#field-authorization)
- [Rate Limiter](#rate-limiter)

Documentation can be found at [https://hexdocs.pm/rajska/](https://hexdocs.pm/rajska).

Expand Down Expand Up @@ -323,6 +324,55 @@ end

As seen in the example above, a function can also be passed as value to the meta `:private` key, in order to check if a field is private dynamically, depending of the value of another field.

### Rate Limiter

Rate limiter absinthe middleware. Uses [Hammer](https://github.com/ExHammer/hammer).

#### Usage

First configure Hammer, following its documentation. For example:

```elixir
config :hammer,
backend: {Hammer.Backend.ETS, [expiry_ms: 60_000 * 60 * 4,
cleanup_interval_ms: 60_000 * 10]}
```

Add your middleware to the query that should be limited:

```elixir
field :default_config, :string do
middleware Rajska.RateLimiter
resolve fn _, _ -> {:ok, "ok"} end
end
```

You can also configure it and use multiple rules for limiting in one query:

```elixir
field :login_user, :session do
arg :email, non_null(:string)
arg :password, non_null(:string)

middleware Rajska.RateLimiter, limit: 10 # Using the default identifier (user IP)
middleware Rajska.RateLimiter, keys: :email, limit: 5 # Using the value provided in the email arg
resolve &AccountsResolver.login_user/2
end
```

The allowed configuration are:

* `scale_ms`: The timespan for the maximum number of actions. Defaults to 60_000.
* `limit`: The maximum number of actions in the specified timespan. Defaults to 10.
* `id`: An atom or string to be used as the bucket identifier. Note that this will always be the same, so by using this the limit will be global instead of by user.
* `keys`: An atom or a list of atoms to get a query argument as identifier. Use a list when the argument is nested.
* `error_msg`: The error message to be displayed when rate limit exceeds. Defaults to `"Too many requests"`.

Note that when neither `id` or `keys` is provided, the default is to use the user's IP. For that, the default behaviour is to use
`c:Rajska.Authorization.get_ip/1` to fetch the IP from the absinthe context. That means you need to manually insert the user's IP in the
absinthe context before using it as an identifier. See the [absinthe docs](https://hexdocs.pm/absinthe/context-and-authentication.html#content)
for more information.

## Related Projects

[Crudry](https://github.com/gabrielpra1/crudry) is an elixir library for DRYing CRUD of Phoenix Contexts and Absinthe Resolvers.
Expand Down
41 changes: 40 additions & 1 deletion lib/middlewares/rate_limiter.ex
Original file line number Diff line number Diff line change
@@ -1,6 +1,45 @@
defmodule Rajska.RateLimiter do
@moduledoc """
Rate limiter absinthe middleware.
Rate limiter absinthe middleware. Uses [Hammer](https://github.com/ExHammer/hammer).
## Usage
First configure Hammer, following its documentation. For example:
config :hammer,
backend: {Hammer.Backend.ETS, [expiry_ms: 60_000 * 60 * 4,
cleanup_interval_ms: 60_000 * 10]}
Add your middleware to the query that should be limited:
field :default_config, :string do
middleware Rajska.RateLimiter
resolve fn _, _ -> {:ok, "ok"} end
end
You can also configure it and use multiple rules for limiting in one query:
field :login_user, :session do
arg :email, non_null(:string)
arg :password, non_null(:string)
middleware Rajska.RateLimiter, limit: 10 # Using the default identifier (user IP)
middleware Rajska.RateLimiter, keys: :email, limit: 5 # Using the value provided in the email arg
resolve &AccountsResolver.login_user/2
end
The allowed configuration are:
* `scale_ms`: The timespan for the maximum number of actions. Defaults to 60_000.
* `limit`: The maximum number of actions in the specified timespan. Defaults to 10.
* `id`: An atom or string to be used as the bucket identifier. Note that this will always be the same, so by using this the limit will be global instead of by user.
* `keys`: An atom or a list of atoms to get a query argument as identifier. Use a list when the argument is nested.
* `error_msg`: The error message to be displayed when rate limit exceeds. Defaults to `"Too many requests"`.
Note that when neither `id` or `keys` is provided, the default is to use the user's IP. For that, the default behaviour is to use
`c:Rajska.Authorization.get_ip/1` to fetch the IP from the absinthe context. That means you need to manually insert the user's IP in the
absinthe context before using it as an identifier. See the [absinthe docs](https://hexdocs.pm/absinthe/context-and-authentication.html#content)
for more information.
"""
@behaviour Absinthe.Middleware

Expand Down

0 comments on commit f0de163

Please sign in to comment.