limiter icon indicating copy to clipboard operation
limiter copied to clipboard

Should it be more convenient to use multiple Rates at the same time?

Open Hubro opened this issue 6 years ago • 1 comments

I want to rate limit my API's login endpoint thusly: max 1 request per second, max 5 requests per hour, max 10 requests per day.

I have implemented it like this using your middleware:

func loginLimiterHandler() http.Handler {
	secondRate := limiter.Rate{Period: 1 * time.Second, Limit: 1}
	hourRate := limiter.Rate{Period: 1 * time.Hour, Limit: 5}
	dayRate := limiter.Rate{Period: 24 * time.Hour, Limit: 10}

	secondLimit := limiter.New(memory.NewStore(), secondRate)
	hourLimit := limiter.New(memory.NewStore(), hourRate)
	dayLimit := limiter.New(memory.NewStore(), dayRate)

	var handler http.Handler = http.HandlerFunc(LoginHandler)

	handler = stdlib.NewMiddleware(dayLimit).Handler(handler)
	handler = stdlib.NewMiddleware(hourLimit).Handler(handler)
	handler = stdlib.NewMiddleware(secondLimit).Handler(handler)

	return handler
}

I think it would be practical to add the function limiter.NewMultipleRates (or similar) to allow this:

func loginLimiterHandler() http.Handler {
	secondRate := limiter.Rate{Period: 1 * time.Second, Limit: 1}
	hourRate := limiter.Rate{Period: 1 * time.Hour, Limit: 5}
	dayRate := limiter.Rate{Period: 24 * time.Hour, Limit: 10}

	limit := limiter.NewMultipleRates(memory.NewStore(), secondRate, hourRate, dayRate)

	return stdlib.NewMiddleware(limit).Handler(http.HandlerFunc(LoginHandler))
}

That way you could also properly display all the right HTTP headers. With my solution, when the second-limit blocks the request, the response doesn't include headers about the hourly or daily limits.

My apologies in advance if I've massively over-complicated my solution.

Hubro avatar Mar 30 '18 15:03 Hubro

Hello,

Thank you for the idea. We'll gladly review your pull request if you want to contribute to the project :slightly_smiling_face:

novln avatar Apr 03 '18 12:04 novln