Skip to content

threatgrid/ring-turnstile-middleware

Repository files navigation

https://travis-ci.com/threatgrid/ring-turnstile-middleware.png?branch=master

ring-turnstile-middleware

Ring middleware for the Turnstile rate limiting service

Changes

  • Note: Version 0.1.1 is missing commit information–it corresponds to this commit.

Basic Usage

Use wrap-rate-limit to create an instance of the middleware, wrap your handler with it:

(require '[ring.middleware.turnstile 
           :refer [wrap-rate-limit ip-limit header-limit]]
         '[ring.util.response :refer [response]])

(def app (-> your-routes
             (wrap-rate-limit {:redis-conf {}
                               :key-prefix "your-api"
                               :limit-fns [(ip-limit 200)
                                           (header-limit 300 "x-role" "ROLE")]))

;; 200 requests per hour per IP address
;; 300 requests per hour per value of the header `x-role`

Advanced usage

Custom rate limit handler

If you want to do some specific operations when a call is rate limited, you can define your own rate limit handler:

(require '[ring.middleware.turnstile :refer [wrap-rate-limit ip-limit]]
         '[ring.util.response :refer [response]])

(def app (-> your-routes
             (wrap-rate-limit {:redis-conf {}
                               :key-prefix "your-api"
                               :limit-fns [(ip-limit 200)]
                               :rate-limit-handler 
                                (fn [request next-slot-in-sec limit]
                                 {:status 429
                                  :body (format "Too many requests, try later in %d s"
                                                next-slot-in-sec)})}))

Custom limit

You can create your own limit

(require '[ring.middleware.turnstile :refer [wrap-rate-limit ip-limit]]
         '[ring.util.response :refer [response]])   

(def custom-limit
  [request]
  (when-let [role (get-in request [:jwt "role"])
             ip-limit-fn (ip-limit 100)]
    (cond-> (ip-limit-fn request)
      (= "admin" role) (assoc :nb-request-per-hour 200))))

(def app (-> your-routes
             (wrap-rate-limit {:redis-conf {}
                               :key-prefix "your-api"
                               :limits [custom-limit]))

;; 200 requests per hour per IP for amdin users
;; 100 requests per hour for the others

The limit fn must return a hash map with the following keys:

KeywordDescription
:nb-request-per-hourThe number of request per hour limit
:rate-limit-keyThe rate limit key to group requests
:name-in-headersUsed in the rate limit headers to identify a rate limit. (templates: X-RateLimit-%s-Limit, X-RateLimit-%s-Limit). Field names in HTTP headers are case-insensitive and are composed by any char except control chars or separators

or

nil if the request is not rate limited.

License

Copyright © 2018 Cisco Systems Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version.

About

Ring middleware for the Turnstile rate limiting service

Resources

License

Stars

Watchers

Forks

Packages

No packages published