timeout limitrate middleware but look like invalid
This commit is contained in:
parent
fe2f6850f9
commit
5dab1f64cd
1
go.mod
1
go.mod
@ -18,6 +18,7 @@ require (
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/jinzhu/gorm v1.9.16
|
||||
github.com/json-iterator/go v1.1.11 // indirect
|
||||
github.com/juju/ratelimit v1.0.1 // indirect
|
||||
github.com/leodido/go-urn v1.2.1 // indirect
|
||||
github.com/magiconair/properties v1.8.5 // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
|
17
internal/middleware/context_timeout.go
Normal file
17
internal/middleware/context_timeout.go
Normal file
@ -0,0 +1,17 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/gin-gonic/gin"
|
||||
"time"
|
||||
)
|
||||
|
||||
func ContextTimeout(t time.Duration) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
ctx, cancel := context.WithTimeout(c.Request.Context(), t)
|
||||
defer cancel()
|
||||
|
||||
c.Request = c.Request.WithContext(ctx)
|
||||
c.Next()
|
||||
}
|
||||
}
|
25
internal/middleware/limiter.go
Normal file
25
internal/middleware/limiter.go
Normal file
@ -0,0 +1,25 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"blog/pkg/app"
|
||||
"blog/pkg/errorcode"
|
||||
"blog/pkg/limiter"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func RateLimiter(l limiter.LimiterIface) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
key := l.Key(c)
|
||||
if bucket, ok := l.GetBucket(key); ok {
|
||||
count := bucket.TakeAvailable(1)
|
||||
if count == 0 {
|
||||
response := app.NewResponse(c)
|
||||
response.ToErrorResponse(errorcode.TooManyRequests)
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
c.Next()
|
||||
}
|
||||
}
|
@ -6,19 +6,33 @@ import (
|
||||
"blog/internal/middleware"
|
||||
"blog/internal/routess/api"
|
||||
v1 "blog/internal/routess/api/v1"
|
||||
"blog/pkg/limiter"
|
||||
"github.com/gin-gonic/gin"
|
||||
swaggerFiles "github.com/swaggo/files"
|
||||
ginSwagger "github.com/swaggo/gin-swagger"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
var methodLimiters = limiter.NewMethodLimiter().AddBuckets(limiter.LimiterBucketRule{
|
||||
Key: "/auth",
|
||||
FillInterval: time.Second,
|
||||
Capacity: 10,
|
||||
Quantum: 10,
|
||||
})
|
||||
|
||||
func NewRouter() *gin.Engine {
|
||||
r := gin.New()
|
||||
r.Use(gin.Logger())
|
||||
r.Use(gin.Recovery())
|
||||
if global.ServerSetting.RunMode == "debug" {
|
||||
r.Use(gin.Logger())
|
||||
r.Use(gin.Recovery())
|
||||
} else {
|
||||
r.Use(middleware.AccessLog())
|
||||
r.Use(middleware.Recovery())
|
||||
}
|
||||
r.Use(middleware.Translations())
|
||||
r.Use(middleware.Recovery())
|
||||
r.Use(middleware.AccessLog())
|
||||
r.Use(middleware.RateLimiter(methodLimiters))
|
||||
r.Use(middleware.ContextTimeout(60 * time.Second))
|
||||
article := v1.NewArticle()
|
||||
tag := v1.NewTag()
|
||||
upload := api.NewUpload()
|
||||
|
24
pkg/limiter/limiter.go
Normal file
24
pkg/limiter/limiter.go
Normal file
@ -0,0 +1,24 @@
|
||||
package limiter
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/juju/ratelimit"
|
||||
"time"
|
||||
)
|
||||
|
||||
type LimiterIface interface {
|
||||
Key(c *gin.Context) string
|
||||
GetBucket(key string) (*ratelimit.Bucket, bool)
|
||||
AddBuckets(rules ...LimiterBucketRule) LimiterIface
|
||||
}
|
||||
|
||||
type Limiter struct {
|
||||
limiterBuckets map[string]*ratelimit.Bucket
|
||||
}
|
||||
|
||||
type LimiterBucketRule struct {
|
||||
Key string
|
||||
FillInterval time.Duration
|
||||
Capacity int64
|
||||
Quantum int64
|
||||
}
|
42
pkg/limiter/method_limiter.go
Normal file
42
pkg/limiter/method_limiter.go
Normal file
@ -0,0 +1,42 @@
|
||||
package limiter
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/juju/ratelimit"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type MethodLimiter struct {
|
||||
*Limiter
|
||||
}
|
||||
|
||||
func NewMethodLimiter() LimiterIface {
|
||||
return MethodLimiter{
|
||||
Limiter: &Limiter{limiterBuckets: make(map[string]*ratelimit.Bucket)},
|
||||
}
|
||||
}
|
||||
|
||||
func (l MethodLimiter) Key(c *gin.Context) string {
|
||||
uri := c.Request.RequestURI
|
||||
index := strings.Index(uri, "?")
|
||||
if index == -1 {
|
||||
return uri
|
||||
}
|
||||
|
||||
return uri[:index]
|
||||
}
|
||||
|
||||
func (l MethodLimiter) GetBucket(key string) (*ratelimit.Bucket, bool) {
|
||||
bucket, ok := l.limiterBuckets[key]
|
||||
return bucket, ok
|
||||
}
|
||||
|
||||
func (l MethodLimiter) AddBuckets(rules ...LimiterBucketRule) LimiterIface {
|
||||
for _, rule := range rules {
|
||||
if _, ok := l.limiterBuckets[rule.Key]; !ok {
|
||||
l.limiterBuckets[rule.Key] = ratelimit.NewBucketWithQuantum(rule.FillInterval, rule.Capacity, rule.Quantum)
|
||||
}
|
||||
}
|
||||
|
||||
return l
|
||||
}
|
Loading…
Reference in New Issue
Block a user