func TestHTTPRateLimit(t *testing.T) { limiter := ctxthrottled.HTTPRateLimit{ RateLimiter: &stubLimiter{}, VaryBy: &pathGetter{}, } handler := limiter.WithRateLimit(nil, ctxhttp.HandlerFunc(func(_ context.Context, w http.ResponseWriter, _ *http.Request) error { w.WriteHeader(200) return nil })) runHTTPTestCases(t, handler, []httpTestCase{ {"ok", 200, map[string]string{"X-Ratelimit-Limit": "1", "X-Ratelimit-Remaining": "2", "X-Ratelimit-Reset": "60"}}, {"error", 500, map[string]string{}}, {"limit", 429, map[string]string{"Retry-After": "60"}}, }) }
func TestCustomHTTPRateLimitHandlers(t *testing.T) { limiter := ctxthrottled.HTTPRateLimit{ RateLimiter: &stubLimiter{}, VaryBy: &pathGetter{}, DeniedHandler: ctxhttp.HandlerFunc(func(_ context.Context, w http.ResponseWriter, _ *http.Request) error { http.Error(w, "custom limit exceeded", 400) return nil }), } handler := limiter.WithRateLimit(nil, ctxhttp.HandlerFunc(func(_ context.Context, w http.ResponseWriter, _ *http.Request) error { w.WriteHeader(200) return nil })) runHTTPTestCases(t, handler, []httpTestCase{ {"limit", 400, map[string]string{}}, {"error", 500, map[string]string{}}, }) }
func TestHTTPRateLimitConfig(t *testing.T) { cr := config.NewMockReader( config.WithMockValues(config.MockPV{ config.MockPathScopeDefault(ctxthrottled.PathRateLimitBurst): 0, config.MockPathScopeDefault(ctxthrottled.PathRateLimitRequests): 1, config.MockPathScopeDefault(ctxthrottled.PathRateLimitDuration): "i", }), ) limiter := ctxthrottled.HTTPRateLimit{ Config: cr, VaryBy: &pathGetter{}, } handler := limiter.WithRateLimit(nil, ctxhttp.HandlerFunc(func(_ context.Context, w http.ResponseWriter, _ *http.Request) error { w.WriteHeader(200) return nil })) runHTTPTestCases(t, handler, []httpTestCase{ {"xx", 200, map[string]string{"X-Ratelimit-Limit": "1", "X-Ratelimit-Remaining": "0", "X-Ratelimit-Reset": "60"}}, {"xx", 429, map[string]string{"X-Ratelimit-Limit": "1", "X-Ratelimit-Remaining": "0", "X-Ratelimit-Reset": "60", "Retry-After": "60"}}, }) }