2020-04-08 20:40:49 +01:00
|
|
|
// Copyright (C) 2019 Storj Labs, Inc.
|
|
|
|
// See LICENSE for copying information.
|
|
|
|
|
|
|
|
package web_test
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"net/http"
|
|
|
|
"net/http/httptest"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/spf13/pflag"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
|
|
|
|
"storj.io/common/testcontext"
|
|
|
|
"storj.io/private/cfgstruct"
|
|
|
|
"storj.io/storj/private/web"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestNewIPRateLimiter(t *testing.T) {
|
2020-10-13 13:47:55 +01:00
|
|
|
// create a rate limiter with defaults except NumLimits = 2
|
2021-08-17 20:38:34 +01:00
|
|
|
config := web.RateLimiterConfig{}
|
2020-04-08 20:40:49 +01:00
|
|
|
cfgstruct.Bind(&pflag.FlagSet{}, &config, cfgstruct.UseDevDefaults())
|
|
|
|
config.NumLimits = 2
|
|
|
|
rateLimiter := web.NewIPRateLimiter(config)
|
2020-10-13 13:47:55 +01:00
|
|
|
|
|
|
|
// run ratelimiter cleanup until end of test
|
2020-04-08 20:40:49 +01:00
|
|
|
ctx := testcontext.New(t)
|
|
|
|
defer ctx.Cleanup()
|
|
|
|
ctx2, cancel := context.WithCancel(ctx)
|
|
|
|
defer cancel()
|
|
|
|
ctx.Go(func() error {
|
|
|
|
rateLimiter.Run(ctx2)
|
|
|
|
return nil
|
|
|
|
})
|
2020-10-13 13:47:55 +01:00
|
|
|
|
|
|
|
// make the default HTTP handler return StatusOK
|
2020-04-08 20:40:49 +01:00
|
|
|
handler := rateLimiter.Limit(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
w.WriteHeader(http.StatusOK)
|
|
|
|
}))
|
2020-10-13 13:47:55 +01:00
|
|
|
|
|
|
|
// expect burst number of successes
|
2021-05-14 16:05:42 +01:00
|
|
|
testWithAddress(ctx, t, "192.168.1.1:5000", rateLimiter.Burst(), handler)
|
2020-10-13 13:47:55 +01:00
|
|
|
// expect similar results for a different IP
|
2021-05-14 16:05:42 +01:00
|
|
|
testWithAddress(ctx, t, "127.0.0.1:5000", rateLimiter.Burst(), handler)
|
2020-10-13 13:47:55 +01:00
|
|
|
// expect similar results for a different IP
|
2021-05-14 16:05:42 +01:00
|
|
|
testWithAddress(ctx, t, "127.0.0.100:5000", rateLimiter.Burst(), handler)
|
2020-10-13 13:47:55 +01:00
|
|
|
// expect original IP to work again because numLimits == 2
|
2021-05-14 16:05:42 +01:00
|
|
|
testWithAddress(ctx, t, "192.168.1.1:5000", rateLimiter.Burst(), handler)
|
2020-04-08 20:40:49 +01:00
|
|
|
}
|
|
|
|
|
2021-05-14 16:05:42 +01:00
|
|
|
func testWithAddress(ctx context.Context, t *testing.T, remoteAddress string, burst int, handler http.Handler) {
|
2020-10-13 13:47:55 +01:00
|
|
|
// create HTTP request
|
2021-05-14 16:05:42 +01:00
|
|
|
req, err := http.NewRequestWithContext(ctx, "GET", "", nil)
|
2020-04-08 20:40:49 +01:00
|
|
|
require.NoError(t, err)
|
|
|
|
req.RemoteAddr = remoteAddress
|
2020-10-13 13:47:55 +01:00
|
|
|
|
|
|
|
// expect burst number of successes
|
2020-04-08 20:40:49 +01:00
|
|
|
for x := 0; x < burst; x++ {
|
|
|
|
rr := httptest.NewRecorder()
|
|
|
|
handler.ServeHTTP(rr, req)
|
|
|
|
assert.Equal(t, rr.Code, http.StatusOK, remoteAddress)
|
|
|
|
}
|
2020-10-13 13:47:55 +01:00
|
|
|
|
|
|
|
// then expect failure
|
2020-04-08 20:40:49 +01:00
|
|
|
rr := httptest.NewRecorder()
|
|
|
|
handler.ServeHTTP(rr, req)
|
|
|
|
assert.Equal(t, rr.Code, http.StatusTooManyRequests, remoteAddress)
|
|
|
|
}
|