Skip to content

Commit d40208e

Browse files
committed
✨ create mutex to handle concurrency problem
1 parent 9b82ead commit d40208e

File tree

4 files changed

+36
-2
lines changed

4 files changed

+36
-2
lines changed

README.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,4 +60,34 @@ func (r *RateLimiter) RateLimiterMiddleware(next http.Handler, limit rate.Limit,
6060
func NewRateLimiter() *RateLimiter {
6161
return &RateLimiter{}
6262
}
63+
```
64+
65+
## Fix Current Access with sync.Mutext
66+
67+
```golang
68+
// RateLimiterMiddleware - 建立 ratelimiter middleware
69+
func (r *RateLimiter) RateLimiterMiddleware(next http.Handler, limit rate.Limit, burst int) http.Handler {
70+
ipLimiterMap := make(map[string]*rate.Limiter)
71+
var mu sync.Mutex
72+
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
73+
// Fetch IP
74+
ip := r.getIP(req)
75+
// Create limiter if not present for IP
76+
mu.Lock()
77+
limiter, exists := ipLimiterMap[ip]
78+
if !exists {
79+
limiter = rate.NewLimiter(limit, burst)
80+
ipLimiterMap[ip] = limiter
81+
}
82+
mu.Unlock()
83+
// return error if the limit has been reached
84+
if !limiter.Allow() {
85+
w.Header().Set("Content-Type", "application/json")
86+
w.WriteHeader(http.StatusTooManyRequests)
87+
json.NewEncoder(w).Encode(map[string]string{"error": "Too many requests"})
88+
return
89+
}
90+
next.ServeHTTP(w, req)
91+
})
92+
}
6393
```

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module github.com/leetcode-golang-classroom/golang-sample-with-rate-limiter
22

3-
go 1.22.4
3+
go 1.24.0
44

55
require (
66
github.com/magefile/mage v1.15.0

internal/application/app.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ func New(appConfig *config.Config) *App {
3434
func (app *App) Start(ctx context.Context) error {
3535
// setup rateLimiter
3636
rateLimitMux := rateLimiter.NewRateLimiter()
37-
handler := rateLimitMux.RateLimiterMiddleware(app.router, rate.Limit(1), 10)
37+
handler := rateLimitMux.RateLimiterMiddleware(app.router, rate.Limit(2), 10)
3838
// setup server
3939
server := &http.Server{
4040
Addr: fmt.Sprintf(":%s", app.appConfig.Port),

internal/service/rate_limiter/rate-limiter.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"log"
66
"net"
77
"net/http"
8+
"sync"
89

910
"golang.org/x/time/rate"
1011
)
@@ -24,15 +25,18 @@ func (r *RateLimiter) getIP(req *http.Request) string {
2425
// RateLimiterMiddleware - 建立 ratelimiter middleware
2526
func (r *RateLimiter) RateLimiterMiddleware(next http.Handler, limit rate.Limit, burst int) http.Handler {
2627
ipLimiterMap := make(map[string]*rate.Limiter)
28+
var mu sync.Mutex
2729
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
2830
// Fetch IP
2931
ip := r.getIP(req)
3032
// Create limiter if not present for IP
33+
mu.Lock()
3134
limiter, exists := ipLimiterMap[ip]
3235
if !exists {
3336
limiter = rate.NewLimiter(limit, burst)
3437
ipLimiterMap[ip] = limiter
3538
}
39+
mu.Unlock()
3640
// return error if the limit has been reached
3741
if !limiter.Allow() {
3842
w.Header().Set("Content-Type", "application/json")

0 commit comments

Comments
 (0)