| 15 | ) |
| 16 | |
| 17 | func TestMarkKeyOnStatus(t *testing.T) { |
| 18 | t.Parallel() |
| 19 | |
| 20 | tests := []struct { |
| 21 | name string |
| 22 | statusCode int |
| 23 | headers map[string]string |
| 24 | expectedReturn bool |
| 25 | expectedState keypool.KeyState |
| 26 | expectedCooldown time.Duration |
| 27 | }{ |
| 28 | { |
| 29 | // 429 with standard Retry-After header (seconds). |
| 30 | name: "429_with_retry_after_seconds", |
| 31 | statusCode: http.StatusTooManyRequests, |
| 32 | headers: map[string]string{"Retry-After": "5"}, |
| 33 | expectedReturn: true, |
| 34 | expectedState: keypool.KeyStateTemporary, |
| 35 | expectedCooldown: 5 * time.Second, |
| 36 | }, |
| 37 | { |
| 38 | // 429 with retry-after-ms header (milliseconds). |
| 39 | name: "429_with_retry_after_ms", |
| 40 | statusCode: http.StatusTooManyRequests, |
| 41 | headers: map[string]string{"retry-after-ms": "1500"}, |
| 42 | expectedReturn: true, |
| 43 | expectedState: keypool.KeyStateTemporary, |
| 44 | expectedCooldown: 1500 * time.Millisecond, |
| 45 | }, |
| 46 | { |
| 47 | // 429 without headers falls back to default cooldown. |
| 48 | name: "429_no_headers_uses_default", |
| 49 | statusCode: http.StatusTooManyRequests, |
| 50 | expectedReturn: true, |
| 51 | expectedState: keypool.KeyStateTemporary, |
| 52 | expectedCooldown: 60 * time.Second, |
| 53 | }, |
| 54 | { |
| 55 | name: "401_marks_permanent", |
| 56 | statusCode: http.StatusUnauthorized, |
| 57 | expectedReturn: true, |
| 58 | expectedState: keypool.KeyStatePermanent, |
| 59 | }, |
| 60 | { |
| 61 | name: "403_marks_permanent", |
| 62 | statusCode: http.StatusForbidden, |
| 63 | expectedReturn: true, |
| 64 | expectedState: keypool.KeyStatePermanent, |
| 65 | }, |
| 66 | { |
| 67 | name: "200_does_not_mark", |
| 68 | statusCode: http.StatusOK, |
| 69 | expectedReturn: false, |
| 70 | expectedState: keypool.KeyStateValid, |
| 71 | }, |
| 72 | { |
| 73 | name: "500_does_not_mark", |
| 74 | statusCode: http.StatusInternalServerError, |