package middleware import ( "net/http" "net/http/httptest" "testing" "time" "github.com/gin-gonic/gin" ) func TestRateLimitByIP_BlocksAfterLimit(t *testing.T) { gin.SetMode(gin.TestMode) r := gin.New() // 1 request per hour, burst 1 => second immediate request should 429. r.Use(RateLimitByIP(1, time.Hour, 1, time.Minute)) r.GET("/", func(c *gin.Context) { c.String(200, "ok") }) req := httptest.NewRequest(http.MethodGet, "/", nil) req.RemoteAddr = "203.0.113.10:1234" w1 := httptest.NewRecorder() r.ServeHTTP(w1, req) if w1.Code != http.StatusOK { t.Fatalf("first request code = %d, want %d", w1.Code, http.StatusOK) } w2 := httptest.NewRecorder() r.ServeHTTP(w2, req) if w2.Code != http.StatusTooManyRequests { t.Fatalf("second request code = %d, want %d", w2.Code, http.StatusTooManyRequests) } } func TestRateLimitByIP_AllowsBurst(t *testing.T) { gin.SetMode(gin.TestMode) r := gin.New() // 1 per hour, but burst 2 => first two immediate requests should pass. r.Use(RateLimitByIP(1, time.Hour, 2, time.Minute)) r.GET("/", func(c *gin.Context) { c.String(200, "ok") }) req := httptest.NewRequest(http.MethodGet, "/", nil) req.RemoteAddr = "203.0.113.11:1234" w1 := httptest.NewRecorder() r.ServeHTTP(w1, req) if w1.Code != http.StatusOK { t.Fatalf("first request code = %d, want %d", w1.Code, http.StatusOK) } w2 := httptest.NewRecorder() r.ServeHTTP(w2, req) if w2.Code != http.StatusOK { t.Fatalf("second request code = %d, want %d", w2.Code, http.StatusOK) } w3 := httptest.NewRecorder() r.ServeHTTP(w3, req) if w3.Code != http.StatusTooManyRequests { t.Fatalf("third request code = %d, want %d", w3.Code, http.StatusTooManyRequests) } }