wip: add api auth and /resume endpoint
This commit is contained in:
parent
22e2f6005f
commit
2c6d063717
28 changed files with 2486 additions and 271 deletions
100
pkg/limiter/limiter.go
Normal file
100
pkg/limiter/limiter.go
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
package limiter
|
||||
|
||||
import (
|
||||
"net"
|
||||
"net/http"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"git.roboces.dev/catalin/cvvvvv/pkg/logger"
|
||||
"github.com/gin-gonic/gin"
|
||||
"golang.org/x/time/rate"
|
||||
)
|
||||
|
||||
// visitor holds limiter and lastSeen for specific user.
|
||||
type visitor struct {
|
||||
limiter *rate.Limiter
|
||||
lastSeen time.Time
|
||||
}
|
||||
|
||||
// rateLimiter used to rate limit an incoming requests.
|
||||
type rateLimiter struct {
|
||||
sync.RWMutex
|
||||
|
||||
visitors map[string]*visitor
|
||||
limit rate.Limit
|
||||
burst int
|
||||
ttl time.Duration
|
||||
}
|
||||
|
||||
// newRateLimiter creates an instance of the rateLimiter.
|
||||
func newRateLimiter(rps, burst int, ttl time.Duration) *rateLimiter {
|
||||
return &rateLimiter{
|
||||
visitors: make(map[string]*visitor),
|
||||
limit: rate.Limit(rps),
|
||||
burst: burst,
|
||||
ttl: ttl,
|
||||
}
|
||||
}
|
||||
|
||||
// getVisitor returns limiter for the specific visitor by its IP,
|
||||
// looking up within the visitors map.
|
||||
func (l *rateLimiter) getVisitor(ip string) *rate.Limiter {
|
||||
l.RLock()
|
||||
v, exists := l.visitors[ip]
|
||||
l.RUnlock()
|
||||
|
||||
if !exists {
|
||||
limiter := rate.NewLimiter(l.limit, l.burst)
|
||||
l.Lock()
|
||||
l.visitors[ip] = &visitor{limiter, time.Now()}
|
||||
l.Unlock()
|
||||
|
||||
return limiter
|
||||
}
|
||||
|
||||
v.lastSeen = time.Now()
|
||||
|
||||
return v.limiter
|
||||
}
|
||||
|
||||
// cleanupVisitors removes old entries from the visitors map.
|
||||
func (l *rateLimiter) cleanupVisitors() {
|
||||
for {
|
||||
time.Sleep(time.Minute)
|
||||
|
||||
l.Lock()
|
||||
for ip, v := range l.visitors {
|
||||
if time.Since(v.lastSeen) > l.ttl {
|
||||
delete(l.visitors, ip)
|
||||
}
|
||||
}
|
||||
l.Unlock()
|
||||
}
|
||||
}
|
||||
|
||||
// Limit creates a new rate limiter middleware handler.
|
||||
func Limit(rps int, burst int, ttl time.Duration) gin.HandlerFunc {
|
||||
l := newRateLimiter(rps, burst, ttl)
|
||||
|
||||
// run a background worker to clean up old entries
|
||||
go l.cleanupVisitors()
|
||||
|
||||
return func(c *gin.Context) {
|
||||
ip, _, err := net.SplitHostPort(c.Request.RemoteAddr)
|
||||
if err != nil {
|
||||
logger.Error(err)
|
||||
c.AbortWithStatus(http.StatusInternalServerError)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if !l.getVisitor(ip).Allow() {
|
||||
c.AbortWithStatus(http.StatusTooManyRequests)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
8
pkg/logger/logger.go
Normal file
8
pkg/logger/logger.go
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
package logger
|
||||
|
||||
type Logger interface {
|
||||
Debug(msg string, params map[string]interface{})
|
||||
Info(msg string, params map[string]interface{})
|
||||
Warn(msg string, params map[string]interface{})
|
||||
Error(msg string, params map[string]interface{})
|
||||
}
|
||||
35
pkg/logger/logrus.go
Normal file
35
pkg/logger/logrus.go
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
package logger
|
||||
|
||||
import "github.com/sirupsen/logrus"
|
||||
|
||||
func Debug(msg ...interface{}) {
|
||||
logrus.Debug(msg...)
|
||||
}
|
||||
|
||||
func Debugf(format string, args ...interface{}) {
|
||||
logrus.Debugf(format, args...)
|
||||
}
|
||||
|
||||
func Info(msg ...interface{}) {
|
||||
logrus.Info(msg...)
|
||||
}
|
||||
|
||||
func Infof(format string, args ...interface{}) {
|
||||
logrus.Infof(format, args...)
|
||||
}
|
||||
|
||||
func Warn(msg ...interface{}) {
|
||||
logrus.Warn(msg...)
|
||||
}
|
||||
|
||||
func Warnf(format string, args ...interface{}) {
|
||||
logrus.Warnf(format, args...)
|
||||
}
|
||||
|
||||
func Error(msg ...interface{}) {
|
||||
logrus.Error(msg...)
|
||||
}
|
||||
|
||||
func Errorf(format string, args ...interface{}) {
|
||||
logrus.Errorf(format, args...)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue