Skip to content

Commit

Permalink
Rate limit endpoint added
Browse files Browse the repository at this point in the history
  • Loading branch information
Martin Buhr committed Dec 12, 2014
1 parent 4a56aa9 commit 87d57db
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 0 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@
- It is now possible to set IP's that shouldn't be tracked by analytics by setting the `ignored_ips` flag in the config file (e.g. for health checks)
- Many core middleware configs moved into tyk common, tyk common can now be cross-seeded into other apps if necessary and is go gettable.
- Added a healthcheck function, calling GET /tyk/health with an api_id param, and the tyk secret header will return upstream latency average, requests per second, throttles per second, quota violations per second and key failure events per second. Can be easily extended to add more data.
- Tyk now reports quote status in response headers (Issue #27)
- Calling /tyk/rate-limits with an authorised header will return the rate limit for the current user without affecting them. Fixes issue #27
35 changes: 35 additions & 0 deletions api.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/Sirupsen/logrus"
"github.com/lonelycode/tykcommon"
"github.com/nu7hatch/gouuid"
"github.com/gorilla/context"
)

// APIModifyKeySuccess represents when a Key modification was successful
Expand Down Expand Up @@ -815,3 +816,37 @@ func healthCheckhandler(w http.ResponseWriter, r *http.Request) {

DoJSONWrite(w, code, responseMessage)
}

func UserRatesCheck() func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
code := 200

thisSessionState := context.Get(r, SessionData)
if thisSessionState == nil {
code = 405
responseMessage := createError("Health checks are not enabled for this node")
DoJSONWrite(w, code, responseMessage)
return
}

userSession := thisSessionState.(SessionState)
returnSession := PublicSessionState{}
returnSession.Quota.QuotaRenews = userSession.QuotaRenews
returnSession.Quota.QuotaRemaining = userSession.QuotaRemaining
returnSession.Quota.QuotaMax = userSession.QuotaMax
returnSession.RateLimit.Rate = userSession.Rate
returnSession.RateLimit.Per = userSession.Per

responseMessage, jsonErr := json.Marshal(returnSession)
if jsonErr != nil {
code = 405
responseMessage = createError("Failed to encode data")
DoJSONWrite(w, code, responseMessage)
return
}

DoJSONWrite(w, code, responseMessage)

return
}
}
9 changes: 9 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,15 @@ func loadApps(APISpecs []APISpec, Muxer *http.ServeMux) {
CreateMiddleware(&AccessRightsCheck{tykMiddleware}, tykMiddleware),
CreateMiddleware(&RateLimitAndQuotaCheck{tykMiddleware}, tykMiddleware)).Then(proxyHandler)

userCheckHandler := http.HandlerFunc(UserRatesCheck())
simpleChain := alice.New(
CreateMiddleware(&IPWhiteListMiddleware{tykMiddleware}, tykMiddleware),
CreateMiddleware(&VersionCheck{tykMiddleware}, tykMiddleware),
keyCheck,
CreateMiddleware(&KeyExpired{tykMiddleware}, tykMiddleware),
CreateMiddleware(&AccessRightsCheck{tykMiddleware}, tykMiddleware)).Then(userCheckHandler)

Muxer.Handle("/tyk/rate-limits/", simpleChain)
Muxer.Handle(referenceSpec.Proxy.ListenPath, chain)
}

Expand Down
12 changes: 12 additions & 0 deletions session_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,18 @@ type SessionState struct {
HmacSecret string `json:"hmac_string"`
}

type PublicSessionState struct {
Quota struct {
QuotaMax int64 `json:"quota_max"`
QuotaRemaining int64 `json:"quota_remaining"`
QuotaRenews int64 `json:"quota_renews"`
} `json:"quota"`
RateLimit struct {
Rate float64 `json:"requests"`
Per float64 `json:"per_unit"`
} `json:"rate_limit"`
}

// SessionLimiter is the rate limiter for the API, use ForwardMessage() to
// check if a message should pass through or not
type SessionLimiter struct{}
Expand Down

0 comments on commit 87d57db

Please sign in to comment.