MCPcopy Index your code
hub / github.com/coder/coder / TestRateLimitByUser

Function TestRateLimitByUser

coderd/coderd_test.go:442–525  ·  view source on GitHub ↗

TestRateLimitByUser verifies that rate limiting keys by user ID when an authenticated session is present, rather than falling back to IP. This is a regression test for https://github.com/coder/coder/issues/20857

(t *testing.T)

Source from the content-addressed store, hash-verified

440// an authenticated session is present, rather than falling back to IP.
441// This is a regression test for https://github.com/coder/coder/issues/20857
442func TestRateLimitByUser(t *testing.T) {
443 t.Parallel()
444
445 const rateLimit = 5
446
447 ownerClient := coderdtest.New(t, &coderdtest.Options{
448 APIRateLimit: rateLimit,
449 })
450 firstUser := coderdtest.CreateFirstUser(t, ownerClient)
451
452 t.Run("HitsLimit", func(t *testing.T) {
453 t.Parallel()
454
455 ctx := testutil.Context(t, testutil.WaitLong)
456
457 // Make rateLimit requests — they should all succeed.
458 for i := 0; i < rateLimit; i++ {
459 req, err := http.NewRequestWithContext(ctx, http.MethodGet,
460 ownerClient.URL.String()+"/api/v2/buildinfo", nil)
461 require.NoError(t, err)
462 req.Header.Set(codersdk.SessionTokenHeader, ownerClient.SessionToken())
463
464 resp, err := ownerClient.HTTPClient.Do(req)
465 require.NoError(t, err)
466 resp.Body.Close()
467 require.Equal(t, http.StatusOK, resp.StatusCode,
468 "request %d should succeed", i+1)
469 }
470
471 // The next request should be rate-limited.
472 req, err := http.NewRequestWithContext(ctx, http.MethodGet,
473 ownerClient.URL.String()+"/api/v2/buildinfo", nil)
474 require.NoError(t, err)
475 req.Header.Set(codersdk.SessionTokenHeader, ownerClient.SessionToken())
476
477 resp, err := ownerClient.HTTPClient.Do(req)
478 require.NoError(t, err)
479 resp.Body.Close()
480 require.Equal(t, http.StatusTooManyRequests, resp.StatusCode,
481 "request should be rate limited")
482 })
483
484 t.Run("BypassOwner", func(t *testing.T) {
485 t.Parallel()
486
487 ctx := testutil.Context(t, testutil.WaitLong)
488
489 // Owner with bypass header should not be rate-limited.
490 for i := 0; i < rateLimit+5; i++ {
491 req, err := http.NewRequestWithContext(ctx, http.MethodGet,
492 ownerClient.URL.String()+"/api/v2/buildinfo", nil)
493 require.NoError(t, err)
494 req.Header.Set(codersdk.SessionTokenHeader, ownerClient.SessionToken())
495 req.Header.Set(codersdk.BypassRatelimitHeader, "true")
496
497 resp, err := ownerClient.HTTPClient.Do(req)
498 require.NoError(t, err)
499 resp.Body.Close()

Callers

nothing calls this directly

Calls 11

NewFunction · 0.92
CreateFirstUserFunction · 0.92
ContextFunction · 0.92
CreateAnotherUserFunction · 0.92
RunMethod · 0.65
SetMethod · 0.65
DoMethod · 0.65
CloseMethod · 0.65
StringMethod · 0.45
SessionTokenMethod · 0.45
EqualMethod · 0.45

Tested by

no test coverage detected