@@ -22,11 +22,12 @@ type ThrottleOpts struct {
22
22
Limit int
23
23
BacklogLimit int
24
24
BacklogTimeout time.Duration
25
+ StatusCode int
25
26
}
26
27
27
28
// Throttle is a middleware that limits number of currently processed requests
28
29
// at a time across all users. Note: Throttle is not a rate-limiter per user,
29
- // instead it just puts a ceiling on the number of currently in-flight requests
30
+ // instead it just puts a ceiling on the number of current in-flight requests
30
31
// being processed from the point from where the Throttle middleware is mounted.
31
32
func Throttle (limit int ) func (http.Handler ) http.Handler {
32
33
return ThrottleWithOpts (ThrottleOpts {Limit : limit , BacklogTimeout : defaultBacklogTimeout })
@@ -49,10 +50,16 @@ func ThrottleWithOpts(opts ThrottleOpts) func(http.Handler) http.Handler {
49
50
panic ("chi/middleware: Throttle expects backlogLimit to be positive" )
50
51
}
51
52
53
+ statusCode := opts .StatusCode
54
+ if statusCode == 0 {
55
+ statusCode = http .StatusTooManyRequests
56
+ }
57
+
52
58
t := throttler {
53
59
tokens : make (chan token , opts .Limit ),
54
60
backlogTokens : make (chan token , opts .Limit + opts .BacklogLimit ),
55
61
backlogTimeout : opts .BacklogTimeout ,
62
+ statusCode : statusCode ,
56
63
retryAfterFn : opts .RetryAfterFn ,
57
64
}
58
65
@@ -72,7 +79,7 @@ func ThrottleWithOpts(opts ThrottleOpts) func(http.Handler) http.Handler {
72
79
73
80
case <- ctx .Done ():
74
81
t .setRetryAfterHeaderIfNeeded (w , true )
75
- http .Error (w , errContextCanceled , http . StatusTooManyRequests )
82
+ http .Error (w , errContextCanceled , t . statusCode )
76
83
return
77
84
78
85
case btok := <- t .backlogTokens :
@@ -85,12 +92,12 @@ func ThrottleWithOpts(opts ThrottleOpts) func(http.Handler) http.Handler {
85
92
select {
86
93
case <- timer .C :
87
94
t .setRetryAfterHeaderIfNeeded (w , false )
88
- http .Error (w , errTimedOut , http . StatusTooManyRequests )
95
+ http .Error (w , errTimedOut , t . statusCode )
89
96
return
90
97
case <- ctx .Done ():
91
98
timer .Stop ()
92
99
t .setRetryAfterHeaderIfNeeded (w , true )
93
- http .Error (w , errContextCanceled , http . StatusTooManyRequests )
100
+ http .Error (w , errContextCanceled , t . statusCode )
94
101
return
95
102
case tok := <- t .tokens :
96
103
defer func () {
@@ -103,7 +110,7 @@ func ThrottleWithOpts(opts ThrottleOpts) func(http.Handler) http.Handler {
103
110
104
111
default :
105
112
t .setRetryAfterHeaderIfNeeded (w , false )
106
- http .Error (w , errCapacityExceeded , http . StatusTooManyRequests )
113
+ http .Error (w , errCapacityExceeded , t . statusCode )
107
114
return
108
115
}
109
116
}
@@ -119,8 +126,9 @@ type token struct{}
119
126
type throttler struct {
120
127
tokens chan token
121
128
backlogTokens chan token
122
- retryAfterFn func (ctxDone bool ) time.Duration
123
129
backlogTimeout time.Duration
130
+ statusCode int
131
+ retryAfterFn func (ctxDone bool ) time.Duration
124
132
}
125
133
126
134
// setRetryAfterHeaderIfNeeded sets Retry-After HTTP header if corresponding retryAfterFn option of throttler is initialized.
0 commit comments