(t *testing.T)
| 149 | } |
| 150 | |
| 151 | func TestRateLimitByAuthToken(t *testing.T) { |
| 152 | t.Parallel() |
| 153 | |
| 154 | t.Run("LimitsByAuthHeader", func(t *testing.T) { |
| 155 | t.Parallel() |
| 156 | |
| 157 | tests := []struct { |
| 158 | name string |
| 159 | headerName string |
| 160 | headerVal string |
| 161 | }{ |
| 162 | { |
| 163 | name: "BearerToken", |
| 164 | headerName: "Authorization", |
| 165 | headerVal: "Bearer test-token-123", |
| 166 | }, |
| 167 | { |
| 168 | name: "XApiKey", |
| 169 | headerName: "X-Api-Key", |
| 170 | headerVal: "test-api-key-456", |
| 171 | }, |
| 172 | { |
| 173 | name: "NoToken", |
| 174 | headerName: "", |
| 175 | headerVal: "", |
| 176 | }, |
| 177 | } |
| 178 | |
| 179 | for _, tt := range tests { |
| 180 | t.Run(tt.name, func(t *testing.T) { |
| 181 | t.Parallel() |
| 182 | rtr := chi.NewRouter() |
| 183 | rtr.Use(httpmw.RateLimitByAuthToken(2, time.Hour)) |
| 184 | rtr.Get("/", func(rw http.ResponseWriter, r *http.Request) { |
| 185 | rw.WriteHeader(http.StatusOK) |
| 186 | }) |
| 187 | |
| 188 | // Same token (or IP if no token) should be rate limited after 2 requests. |
| 189 | for i := 0; i < 5; i++ { |
| 190 | req := httptest.NewRequest("GET", "/", nil) |
| 191 | if tt.headerName != "" { |
| 192 | req.Header.Set(tt.headerName, tt.headerVal) |
| 193 | } |
| 194 | rec := httptest.NewRecorder() |
| 195 | rtr.ServeHTTP(rec, req) |
| 196 | resp := rec.Result() |
| 197 | _ = resp.Body.Close() |
| 198 | if i < 2 { |
| 199 | require.Equal(t, http.StatusOK, resp.StatusCode, "request %d should succeed", i) |
| 200 | } else { |
| 201 | require.Equal(t, http.StatusTooManyRequests, resp.StatusCode, "request %d should be rate limited", i) |
| 202 | // Verify Retry-After header is set. |
| 203 | require.NotEmpty(t, resp.Header.Get("Retry-After"), "Retry-After header should be set") |
| 204 | } |
| 205 | } |
| 206 | }) |
| 207 | } |
| 208 | }) |
nothing calls this directly
no test coverage detected