@@ -62,34 +62,31 @@ type rateLimiter struct {
62
62
mu sync.Mutex
63
63
}
64
64
65
- func (r * rateLimiter ) Counter () LimitCounter {
66
- return r .limitCounter
65
+ func (l * rateLimiter ) Counter () LimitCounter {
66
+ return l .limitCounter
67
67
}
68
68
69
- func (r * rateLimiter ) Status (key string ) (bool , float64 , error ) {
69
+ func (l * rateLimiter ) Status (key string ) (bool , float64 , error ) {
70
70
t := time .Now ().UTC ()
71
- currentWindow := t .Truncate (r .windowLength )
72
- previousWindow := currentWindow .Add (- r .windowLength )
71
+ currentWindow := t .Truncate (l .windowLength )
72
+ previousWindow := currentWindow .Add (- l .windowLength )
73
73
74
- currCount , prevCount , err := r .limitCounter .Get (key , currentWindow , previousWindow )
74
+ currCount , prevCount , err := l .limitCounter .Get (key , currentWindow , previousWindow )
75
75
if err != nil {
76
76
return false , 0 , err
77
77
}
78
78
79
79
diff := t .Sub (currentWindow )
80
- rate := float64 (prevCount )* (float64 (r .windowLength )- float64 (diff ))/ float64 (r .windowLength ) + float64 (currCount )
80
+ rate := float64 (prevCount )* (float64 (l .windowLength )- float64 (diff ))/ float64 (l .windowLength ) + float64 (currCount )
81
81
82
- if rate > float64 (r .requestLimit ) {
82
+ if rate > float64 (l .requestLimit ) {
83
83
return false , rate , nil
84
84
}
85
85
return true , rate , nil
86
86
}
87
87
88
88
func (l * rateLimiter ) Handler (next http.Handler ) http.Handler {
89
89
return http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
90
- l .mu .Lock ()
91
- defer l .mu .Unlock ()
92
-
93
90
key , err := l .keyFn (r )
94
91
if err != nil {
95
92
http .Error (w , err .Error (), http .StatusPreconditionRequired )
@@ -102,8 +99,10 @@ func (l *rateLimiter) Handler(next http.Handler) http.Handler {
102
99
w .Header ().Set ("X-RateLimit-Remaining" , fmt .Sprintf ("%d" , 0 ))
103
100
w .Header ().Set ("X-RateLimit-Reset" , fmt .Sprintf ("%d" , currentWindow .Add (l .windowLength ).Unix ()))
104
101
102
+ l .mu .Lock ()
105
103
_ , rate , err := l .Status (key )
106
104
if err != nil {
105
+ l .mu .Unlock ()
107
106
http .Error (w , err .Error (), http .StatusPreconditionRequired )
108
107
return
109
108
}
@@ -114,16 +113,19 @@ func (l *rateLimiter) Handler(next http.Handler) http.Handler {
114
113
}
115
114
116
115
if nrate >= l .requestLimit {
116
+ l .mu .Unlock ()
117
117
w .Header ().Set ("Retry-After" , fmt .Sprintf ("%d" , int (l .windowLength .Seconds ()))) // RFC 6585
118
118
l .onRequestLimit (w , r )
119
119
return
120
120
}
121
121
122
122
err = l .limitCounter .Increment (key , currentWindow )
123
123
if err != nil {
124
+ l .mu .Unlock ()
124
125
http .Error (w , err .Error (), http .StatusInternalServerError )
125
126
return
126
127
}
128
+ l .mu .Unlock ()
127
129
128
130
next .ServeHTTP (w , r )
129
131
})
0 commit comments