Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More complex limits #62

Closed
Hubro opened this issue Mar 29, 2018 · 3 comments
Closed

More complex limits #62

Hubro opened this issue Mar 29, 2018 · 3 comments

Comments

@Hubro
Copy link

Hubro commented Mar 29, 2018

For my login API endpoint, I want to allow 1 login attempt per second, 5 attempts per hour and 10 attempts per 24 hours.

I have read through the README example and I've looked through the API, and I can't see any way to achieve this. My apologies in advance if I'm just being thick, but is this possible using this library? Would I have to stack 3 levels of the middleware?

Here's where I'm at:

func loginLimiterHandle() http.Handler {
	secondLimiter := tollbooth.NewLimiter(1, nil)

	hourLimiter := tollbooth.NewLimiter(5, nil)
	hourLimiter.SetTokenBucketExpirationTTL(1 * time.Hour)

	dayLimiter := tollbooth.NewLimiter(10, nil)
	dayLimiter.SetTokenBucketExpirationTTL(24 * time.Hour)

	handler := tollbooth.LimitFuncHandler(dayLimiter, LoginHandler)
	handler = tollbooth.LimitHandler(hourLimiter, handler)
	handler = tollbooth.LimitHandler(secondLimiter, handler)

	return handler
}

And it's only blocking 1 request per second, it's not blocking anything hourly or daily. Tested by sending 10 requests in 10 seconds.

@didip
Copy link
Owner

didip commented Apr 16, 2018

@Hubro Sorry for the late reply, somehow I wasn't notified by GitHub.

At it's core, Tollbooth is nothing but key-value in-memory storage with TTL.

To accomplish what you want, you need to construct your own keys and run LimitByKeys yourself. See: LimitByRequest, BuildKeys, and LimitByKeys for examples.

Re-wrapping 3 times (as what you did in the example), will simply override your key three times, which means the last one set wins (the second limiter one).

I hope that make sense.

@zhp1254
Copy link

zhp1254 commented Oct 12, 2018

if emailLimiterPeer == nil{
		emailLimiterPeer = tollbooth.NewLimiter(1, nil)
	}

	if emailLimiterHour == nil{
		//emailLimiterHour = tollbooth.NewLimiter(0.034, nil)
		emailLimiterHour = tollbooth.NewLimiter(2, nil)
		emailLimiterHour.SetTokenBucketExpirationTTL(1 * time.Hour)
	}

	key := strings.TrimSpace("emailLimiter:"+ctx.FormValue("email"))
	for _, l := range []*limiter.Limiter{emailLimiterPeer, emailLimiterHour} {
		httpError := tollbooth.LimitByKeys(l, []string{key})
		if httpError != nil {
			ctx.JSON(iris.Map{"error": true, "msg": "rate limit."})
			return
		}
	}

it seems not support complex limits, the above code only limit 1 per second

@didip didip closed this as completed Jul 23, 2019
@ghost
Copy link

ghost commented Mar 26, 2020

How did you solve it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants