mirror of
https://github.com/tiennm99/goclaw.git
synced 2026-10-13 08:15:29 +00:00
- config: align struct tag formatting in TelemetryConfig for readability - audio tests: modernize test patterns - cache, http, hooks, providers: small style and cleanup passes - No functional changes
77 lines
2.0 KiB
Go
77 lines
2.0 KiB
Go
package http
|
|
|
|
import (
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
)
|
|
|
|
func TestPerKeyRateLimiter_AllowThenBlock(t *testing.T) {
|
|
rl := newPerKeyRateLimiter(60, 2) // 1 rps, burst 2
|
|
|
|
// First two requests for key A succeed (burst).
|
|
for i := range 2 {
|
|
if !rl.Allow("A") {
|
|
t.Fatalf("request %d should be allowed", i)
|
|
}
|
|
}
|
|
// Third immediate request should be blocked.
|
|
if rl.Allow("A") {
|
|
t.Error("third immediate request should be rate-limited")
|
|
}
|
|
// Independent key is unaffected.
|
|
if !rl.Allow("B") {
|
|
t.Error("different key should not be rate-limited")
|
|
}
|
|
}
|
|
|
|
func TestPerKeyRateLimiter_Disabled(t *testing.T) {
|
|
rl := newPerKeyRateLimiter(0, 5)
|
|
for i := range 100 {
|
|
if !rl.Allow("x") {
|
|
t.Fatalf("disabled limiter should always allow (i=%d)", i)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestRateLimitKeyFromRequest(t *testing.T) {
|
|
// Authenticated user: prefix with uid:.
|
|
r := httptest.NewRequest(http.MethodGet, "/x", nil)
|
|
r.Header.Set("X-GoClaw-User-Id", "alice")
|
|
if got := rateLimitKeyFromRequest(r); got != "uid:alice" {
|
|
t.Errorf("want uid:alice, got %s", got)
|
|
}
|
|
|
|
// Anonymous: fall back to IP.
|
|
r2 := httptest.NewRequest(http.MethodGet, "/x", nil)
|
|
r2.RemoteAddr = "203.0.113.5:54321"
|
|
if got := rateLimitKeyFromRequest(r2); got != "ip:203.0.113.5" {
|
|
t.Errorf("want ip:203.0.113.5, got %s", got)
|
|
}
|
|
}
|
|
|
|
func TestEnforceGitHubReleasesLimit_Writes429(t *testing.T) {
|
|
// Swap the package-level limiter for a tight one, restore after.
|
|
prev := githubReleasesLimiter
|
|
githubReleasesLimiter = newPerKeyRateLimiter(60, 1) // burst 1
|
|
defer func() { githubReleasesLimiter = prev }()
|
|
|
|
r := httptest.NewRequest(http.MethodGet, "/x", nil)
|
|
r.Header.Set("X-GoClaw-User-Id", "bob")
|
|
|
|
w1 := httptest.NewRecorder()
|
|
if !enforceGitHubReleasesLimit(w1, r) {
|
|
t.Fatal("first call should pass")
|
|
}
|
|
w2 := httptest.NewRecorder()
|
|
if enforceGitHubReleasesLimit(w2, r) {
|
|
t.Fatal("second call should be throttled")
|
|
}
|
|
if w2.Code != http.StatusTooManyRequests {
|
|
t.Errorf("want 429, got %d", w2.Code)
|
|
}
|
|
if w2.Header().Get("Retry-After") == "" {
|
|
t.Error("Retry-After header missing")
|
|
}
|
|
}
|