forked from didip/tollbooth
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtollbooth_bug_report_test.go
133 lines (106 loc) · 4 KB
/
tollbooth_bug_report_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
package tollbooth
import (
"net/http"
"net/http/httptest"
"testing"
"time"
"github.com/ntt360/tollbooth/v6/limiter"
)
// See: https://github.com/didip/tollbooth/issues/48
func Test_Issue48_RequestTerminatedEvenOnLowVolumeOnSameIP(t *testing.T) {
// The issue seen by the reporter is that the limiter slowly "leaks", causing requests
// to fail after a prolonged period of continuous usage. Try to model that here.
//
// Report stated that a constant 2 requests per second over several minutes would cause
// a limit of 2/req/sec to start returning 429.
requestsPerSecond := float64(2)
lmt := NewLimiter(requestsPerSecond, nil)
lmt.SetMethods([]string{"GET"})
limitReachedCounter := 0
lmt.SetOnLimitReached(func(w http.ResponseWriter, r *http.Request) { limitReachedCounter++ })
handler := LimitHandler(lmt, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(`hello world`))
}))
timeout := time.After(1 * time.Second)
start := time.Now()
// Create the HTTP request
req, _ := http.NewRequest("GET", "/doesntmatter", nil)
req.RemoteAddr = "127.0.0.1"
Top:
for {
select {
case <-timeout:
break Top
case <-time.After(500 * time.Millisecond):
rr := httptest.NewRecorder()
handler.ServeHTTP(rr, req)
if rr.Code != http.StatusOK {
t.Fatalf("Should be able to handle %v reqs/second. HTTP status: %v. Expected HTTP status: %v. Failed in %v seconds. limitReachedCounter: %d", requestsPerSecond, rr.Code, http.StatusOK, time.Since(start).Seconds(), limitReachedCounter)
}
}
}
if limitReachedCounter > 0 {
t.Fatalf("We should never reached the limit, the counter should be 0. limitReachedCounter: %v", limitReachedCounter)
}
}
var issue66HeaderKey = "X-Customer-ID"
func issue66RateLimiter(h http.HandlerFunc, customerIDs []string) (http.HandlerFunc, *limiter.Limiter) {
allocationLimiter := NewLimiter(1, nil).SetMethods([]string{"POST"})
handler := func(w http.ResponseWriter, r *http.Request) {
allocationLimiter.SetHeader(issue66HeaderKey, customerIDs)
LimitFuncHandler(allocationLimiter, h).ServeHTTP(w, r)
}
return handler, allocationLimiter
}
// See: https://github.com/didip/tollbooth/issues/66
func Test_Issue66_CustomRateLimitByHeaderValues(t *testing.T) {
customerID1 := "1234"
customerID2 := "5678"
h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})
h, allocationLimiter := issue66RateLimiter(h, []string{customerID1, customerID2})
testServer := httptest.NewServer(h)
defer testServer.Close()
client := &http.Client{}
// subtest 1:
// There are 2 different customer ids,
// both should pass rate limiter the 1st time and failed the second time.
request1, _ := http.NewRequest("POST", testServer.URL, nil)
request1.Header.Add(issue66HeaderKey, customerID1)
request2, _ := http.NewRequest("POST", testServer.URL, nil)
request2.Header.Add(issue66HeaderKey, customerID2)
for _, request := range []*http.Request{request1} {
// 1st, 200
response, _ := client.Do(request)
if response.StatusCode != http.StatusOK {
t.Fatalf(`
Customer %v must pass rate limiter the first time.
Expected to receive: %v status code. Got: %v.
limiter.headers: %v`,
request.Header.Get(issue66HeaderKey),
http.StatusOK, response.StatusCode,
allocationLimiter.GetHeaders())
}
// 2nd, 429
response, _ = client.Do(request)
if response.StatusCode != http.StatusTooManyRequests {
t.Fatalf(`Both customer must pass rate limiter.
Expected to receive: %v status code. Got: %v`,
http.StatusTooManyRequests, response.StatusCode)
}
}
// subtest 2:
// There is 1 customer not defined in rate limiter.
// S/he should not be rate limited.
request3, _ := http.NewRequest("POST", testServer.URL, nil)
request3.Header.Add(issue66HeaderKey, "777")
for i := 0; i < 2; i++ {
response, _ := client.Do(request3)
if response.StatusCode != http.StatusOK {
t.Fatalf(`
Customer %v must always pass rate limiter.
Expected to receive: %v status code. Got: %v`,
request3.Header.Get(issue66HeaderKey),
http.StatusOK, response.StatusCode)
}
}
}