diff options
| author | 2023-01-03 10:50:59 +0000 | |
|---|---|---|
| committer | 2023-01-03 11:50:59 +0100 | |
| commit | 71dfea7e47eef3d89b0c4919d71a6ad58e35912d (patch) | |
| tree | e2585e1b50865fff4d57f8270a4a388bcf61f8c7 /internal | |
| parent | [docs] Add troubleshooting section for Apache (#1291) (diff) | |
| download | gotosocial-71dfea7e47eef3d89b0c4919d71a6ad58e35912d.tar.xz | |
[chore] shuffle middleware to split rate limitting into client/s2s/fileserver, share gzip middleware globally (#1290)
Signed-off-by: kim <grufwub@gmail.com>
Signed-off-by: kim <grufwub@gmail.com>
Diffstat (limited to 'internal')
| -rw-r--r-- | internal/api/activitypub.go | 11 | ||||
| -rw-r--r-- | internal/api/auth.go | 11 | ||||
| -rw-r--r-- | internal/api/client.go | 6 | ||||
| -rw-r--r-- | internal/api/fileserver.go | 5 | ||||
| -rw-r--r-- | internal/api/nodeinfo.go | 9 | ||||
| -rw-r--r-- | internal/api/wellknown.go | 6 | ||||
| -rw-r--r-- | internal/middleware/gzip.go | 12 | ||||
| -rw-r--r-- | internal/middleware/ratelimit.go | 30 | ||||
| -rw-r--r-- | internal/web/web.go | 3 | 
9 files changed, 47 insertions, 46 deletions
diff --git a/internal/api/activitypub.go b/internal/api/activitypub.go index 68c3b81e0..70b696834 100644 --- a/internal/api/activitypub.go +++ b/internal/api/activitypub.go @@ -22,6 +22,7 @@ import (  	"context"  	"net/url" +	"github.com/gin-gonic/gin"  	"github.com/superseriousbusiness/gotosocial/internal/api/activitypub/emoji"  	"github.com/superseriousbusiness/gotosocial/internal/api/activitypub/users"  	"github.com/superseriousbusiness/gotosocial/internal/db" @@ -37,20 +38,20 @@ type ActivityPub struct {  	isURIBlocked func(context.Context, *url.URL) (bool, db.Error)  } -func (a *ActivityPub) Route(r router.Router) { +func (a *ActivityPub) Route(r router.Router, m ...gin.HandlerFunc) {  	// create groupings for the 'emoji' and 'users' prefixes  	emojiGroup := r.AttachGroup("emoji")  	usersGroup := r.AttachGroup("users")  	// instantiate + attach shared, non-global middlewares to both of these groups  	var ( -		rateLimitMiddleware      = middleware.RateLimit() // nolint:contextcheck  		signatureCheckMiddleware = middleware.SignatureCheck(a.isURIBlocked) -		gzipMiddleware           = middleware.Gzip()  		cacheControlMiddleware   = middleware.CacheControl("no-store")  	) -	emojiGroup.Use(rateLimitMiddleware, signatureCheckMiddleware, gzipMiddleware, cacheControlMiddleware) -	usersGroup.Use(rateLimitMiddleware, signatureCheckMiddleware, gzipMiddleware, cacheControlMiddleware) +	emojiGroup.Use(m...) +	usersGroup.Use(m...) +	emojiGroup.Use(signatureCheckMiddleware, cacheControlMiddleware) +	usersGroup.Use(signatureCheckMiddleware, cacheControlMiddleware)  	a.emoji.Route(emojiGroup.Handle)  	a.users.Route(usersGroup.Handle) diff --git a/internal/api/auth.go b/internal/api/auth.go index 472c6922a..48131dc3b 100644 --- a/internal/api/auth.go +++ b/internal/api/auth.go @@ -19,6 +19,7 @@  package api  import ( +	"github.com/gin-gonic/gin"  	"github.com/superseriousbusiness/gotosocial/internal/api/auth"  	"github.com/superseriousbusiness/gotosocial/internal/db"  	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" @@ -36,20 +37,20 @@ type Auth struct {  }  // Route attaches 'auth' and 'oauth' groups to the given router. -func (a *Auth) Route(r router.Router) { +func (a *Auth) Route(r router.Router, m ...gin.HandlerFunc) {  	// create groupings for the 'auth' and 'oauth' prefixes  	authGroup := r.AttachGroup("auth")  	oauthGroup := r.AttachGroup("oauth")  	// instantiate + attach shared, non-global middlewares to both of these groups  	var ( -		rateLimitMiddleware    = middleware.RateLimit() // nolint:contextcheck -		gzipMiddleware         = middleware.Gzip()  		cacheControlMiddleware = middleware.CacheControl("private", "max-age=120")  		sessionMiddleware      = middleware.Session(a.sessionName, a.routerSession.Auth, a.routerSession.Crypt)  	) -	authGroup.Use(rateLimitMiddleware, gzipMiddleware, cacheControlMiddleware, sessionMiddleware) -	oauthGroup.Use(rateLimitMiddleware, gzipMiddleware, cacheControlMiddleware, sessionMiddleware) +	authGroup.Use(m...) +	oauthGroup.Use(m...) +	authGroup.Use(cacheControlMiddleware, sessionMiddleware) +	oauthGroup.Use(cacheControlMiddleware, sessionMiddleware)  	a.auth.RouteAuth(authGroup.Handle)  	a.auth.RouteOauth(oauthGroup.Handle) diff --git a/internal/api/client.go b/internal/api/client.go index 7736a99f4..0874664a4 100644 --- a/internal/api/client.go +++ b/internal/api/client.go @@ -19,6 +19,7 @@  package api  import ( +	"github.com/gin-gonic/gin"  	"github.com/superseriousbusiness/gotosocial/internal/api/client/accounts"  	"github.com/superseriousbusiness/gotosocial/internal/api/client/admin"  	"github.com/superseriousbusiness/gotosocial/internal/api/client/apps" @@ -67,15 +68,14 @@ type Client struct {  	user           *user.Module           // api/v1/user  } -func (c *Client) Route(r router.Router) { +func (c *Client) Route(r router.Router, m ...gin.HandlerFunc) {  	// create a new group on the top level client 'api' prefix  	apiGroup := r.AttachGroup("api")  	// attach non-global middlewares appropriate to the client api +	apiGroup.Use(m...)  	apiGroup.Use(  		middleware.TokenCheck(c.db, c.processor.OAuthValidateBearerToken), -		middleware.RateLimit(), -		middleware.Gzip(),  		middleware.CacheControl("no-store"), // never cache api responses  	) diff --git a/internal/api/fileserver.go b/internal/api/fileserver.go index 8784a8663..83aceadd1 100644 --- a/internal/api/fileserver.go +++ b/internal/api/fileserver.go @@ -19,6 +19,7 @@  package api  import ( +	"github.com/gin-gonic/gin"  	"github.com/superseriousbusiness/gotosocial/internal/api/fileserver"  	"github.com/superseriousbusiness/gotosocial/internal/middleware"  	"github.com/superseriousbusiness/gotosocial/internal/processing" @@ -29,12 +30,12 @@ type Fileserver struct {  	fileserver *fileserver.Module  } -func (f *Fileserver) Route(r router.Router) { +func (f *Fileserver) Route(r router.Router, m ...gin.HandlerFunc) {  	fileserverGroup := r.AttachGroup("fileserver")  	// attach middlewares appropriate for this group +	fileserverGroup.Use(m...)  	fileserverGroup.Use( -		middleware.RateLimit(),  		// Since we'll never host different files at the same  		// URL (bc the ULIDs are generated per piece of media),  		// it's sensible and safe to use a long cache here, so diff --git a/internal/api/nodeinfo.go b/internal/api/nodeinfo.go index 906703434..cfab289c8 100644 --- a/internal/api/nodeinfo.go +++ b/internal/api/nodeinfo.go @@ -19,6 +19,7 @@  package api  import ( +	"github.com/gin-gonic/gin"  	"github.com/superseriousbusiness/gotosocial/internal/api/nodeinfo"  	"github.com/superseriousbusiness/gotosocial/internal/middleware"  	"github.com/superseriousbusiness/gotosocial/internal/processing" @@ -29,15 +30,15 @@ type NodeInfo struct {  	nodeInfo *nodeinfo.Module  } -func (w *NodeInfo) Route(r router.Router) { +func (w *NodeInfo) Route(r router.Router, m ...gin.HandlerFunc) {  	// group nodeinfo endpoints together  	nodeInfoGroup := r.AttachGroup("nodeinfo")  	// attach middlewares appropriate for this group +	nodeInfoGroup.Use(m...)  	nodeInfoGroup.Use( -		middleware.Gzip(), -		middleware.RateLimit(), -		middleware.CacheControl("public", "max-age=120"), // allow cache for 2 minutes +		// allow cache for 2 minutes +		middleware.CacheControl("public", "max-age=120"),  	)  	w.nodeInfo.Route(nodeInfoGroup.Handle) diff --git a/internal/api/wellknown.go b/internal/api/wellknown.go index e4fe15f94..62532f292 100644 --- a/internal/api/wellknown.go +++ b/internal/api/wellknown.go @@ -19,6 +19,7 @@  package api  import ( +	"github.com/gin-gonic/gin"  	"github.com/superseriousbusiness/gotosocial/internal/api/wellknown/nodeinfo"  	"github.com/superseriousbusiness/gotosocial/internal/api/wellknown/webfinger"  	"github.com/superseriousbusiness/gotosocial/internal/middleware" @@ -31,14 +32,13 @@ type WellKnown struct {  	webfinger *webfinger.Module  } -func (w *WellKnown) Route(r router.Router) { +func (w *WellKnown) Route(r router.Router, m ...gin.HandlerFunc) {  	// group .well-known endpoints together  	wellKnownGroup := r.AttachGroup(".well-known")  	// attach middlewares appropriate for this group +	wellKnownGroup.Use(m...)  	wellKnownGroup.Use( -		middleware.Gzip(), -		middleware.RateLimit(),  		// allow .well-known responses to be cached for 2 minutes  		middleware.CacheControl("public", "max-age=120"),  	) diff --git a/internal/middleware/gzip.go b/internal/middleware/gzip.go index ddea62b63..4523b4ea3 100644 --- a/internal/middleware/gzip.go +++ b/internal/middleware/gzip.go @@ -19,12 +19,18 @@  package middleware  import ( -	ginGzip "github.com/gin-contrib/gzip" +	"github.com/gin-contrib/gzip"  	"github.com/gin-gonic/gin"  )  // Gzip returns a gzip gin middleware using default compression.  func Gzip() gin.HandlerFunc { -	// todo: make this configurable -	return ginGzip.Gzip(ginGzip.DefaultCompression) +	const enabled = true + +	if !enabled { +		// use noop middleware if gzip is disabled +		return func(ctx *gin.Context) {} +	} + +	return gzip.Gzip(gzip.DefaultCompression)  } diff --git a/internal/middleware/ratelimit.go b/internal/middleware/ratelimit.go index ab947a124..48f15eae5 100644 --- a/internal/middleware/ratelimit.go +++ b/internal/middleware/ratelimit.go @@ -24,7 +24,6 @@ import (  	"time"  	"github.com/gin-gonic/gin" -	"github.com/superseriousbusiness/gotosocial/internal/config"  	"github.com/ulule/limiter/v3"  	limitergin "github.com/ulule/limiter/v3/drivers/middleware/gin"  	"github.com/ulule/limiter/v3/drivers/store/memory" @@ -44,34 +43,25 @@ const rateLimitPeriod = 5 * time.Minute  //  // If the config AdvancedRateLimitRequests value is <= 0, then a noop handler will be returned,  // which performs no rate limiting. -func RateLimit() gin.HandlerFunc { -	// only enable rate limit middleware if configured -	// advanced-rate-limit-requests is greater than 0 -	rateLimitRequests := config.GetAdvancedRateLimitRequests() -	if rateLimitRequests <= 0 { +func RateLimit(limit int) gin.HandlerFunc { +	if limit <= 0 {  		// use noop middleware if ratelimiting is disabled -		return func(c *gin.Context) {} +		return func(ctx *gin.Context) {}  	} -	rate := limiter.Rate{ -		Period: rateLimitPeriod, -		Limit:  int64(rateLimitRequests), -	} - -	limiterInstance := limiter.New( +	limiter := limiter.New(  		memory.NewStore(), -		rate, +		limiter.Rate{Period: rateLimitPeriod, Limit: int64(limit)},  		limiter.WithIPv6Mask(net.CIDRMask(64, 128)), // apply /64 mask to IPv6 addresses  	) -	limitReachedHandler := func(c *gin.Context) { +	// use custom rate limit reached error +	handler := func(c *gin.Context) {  		c.AbortWithStatusJSON(http.StatusTooManyRequests, gin.H{"error": "rate limit reached"})  	} -	middleware := limitergin.NewMiddleware( -		limiterInstance, -		limitergin.WithLimitReachedHandler(limitReachedHandler), // use custom rate limit reached error +	return limitergin.NewMiddleware( +		limiter, +		limitergin.WithLimitReachedHandler(handler),  	) - -	return middleware  } diff --git a/internal/web/web.go b/internal/web/web.go index f263c4655..f8d355ffe 100644 --- a/internal/web/web.go +++ b/internal/web/web.go @@ -68,7 +68,7 @@ func New(processor processing.Processor) *Module {  	}  } -func (m *Module) Route(r router.Router) { +func (m *Module) Route(r router.Router, mi ...gin.HandlerFunc) {  	// serve static files from assets dir at /assets  	assetsGroup := r.AttachGroup(assetsPathPrefix)  	webAssetsAbsFilePath, err := filepath.Abs(config.GetWebAssetBaseDir()) @@ -80,6 +80,7 @@ func (m *Module) Route(r router.Router) {  	// use the cache middleware on all handlers in this group  	assetsGroup.Use(m.assetsCacheControlMiddleware(fs)) +	assetsGroup.Use(mi...)  	// serve static file system in the root of this group,  	// will end up being something like "/assets/"  | 
