~bigbes/core-go

33acd1b0dd23e1e3e2316cd605db1a695b2e9fab — Drew DeVault 10 months ago 565df04
feature: add submodule + middleware for feature flags
2 files changed, 59 insertions(+), 1 deletions(-)

A feature/header.go
M server/server.go
A feature/header.go => feature/header.go +48 -0
@@ 0,0 1,48 @@
package feature

import (
	"context"
	"net/http"
	"strings"
)

var featureCtxKey = &contextKey{"feature"}

type contextKey struct {
	name string
}

// Creates an HTTP middleware to process Accept-Features headers.
func Middleware() func(http.Handler) http.Handler {
	return func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			header := r.Header.Get("Accept-Features")
			features := strings.Split(header, ",")

			ctx := context.WithValue(r.Context(),
				featureCtxKey, features)
			r = r.WithContext(ctx)
			next.ServeHTTP(w, r)
		})
	}
}

// Returns the list of enabled features on this context.
func ForContext(ctx context.Context) []string {
	raw, ok := ctx.Value(featureCtxKey).([]string)
	if !ok {
		return []string{}
	}
	return raw
}

// Returns true if the requested feature is enabled via the Accept-Features
// HTTP header
func Enabled(ctx context.Context, name string) bool {
	for _, feat := range ForContext(ctx) {
		if feat == name {
			return true
		}
	}
	return false
}

M server/server.go => server/server.go +11 -1
@@ 39,6 39,7 @@ import (
	"git.sr.ht/~sircmpwn/core-go/crypto"
	"git.sr.ht/~sircmpwn/core-go/database"
	"git.sr.ht/~sircmpwn/core-go/email"
	"git.sr.ht/~sircmpwn/core-go/feature"
	"git.sr.ht/~sircmpwn/core-go/redis"
)



@@ 254,7 255,15 @@ func (server *Server) WithDefaultMiddleware() *Server {
	server.router.Use(cors.Handler(cors.Options{
		AllowedOrigins: []string{"*"},
		AllowedMethods: []string{"GET", "POST", "OPTIONS"},
		AllowedHeaders: []string{"User-Agent", "X-Requested-With", "If-Modified-Since", "Cache-Control", "Content-Type", "Range"},
		AllowedHeaders: []string{
			"User-Agent",
			"X-Requested-With",
			"If-Modified-Since",
			"Cache-Control",
			"Content-Type",
			"Range",
			"Accept-Features",
		},
		ExposedHeaders: []string{"Content-Length", "Content-Range"},
		MaxAge:         1728000,
	}))


@@ 264,6 273,7 @@ func (server *Server) WithDefaultMiddleware() *Server {
	server.router.Use(redis.Middleware(rc))
	server.router.Use(auth.Middleware(server.conf, apiconf))
	server.router.Use(middleware.RealIP)
	server.router.Use(feature.Middleware())
	if debug {
		server.router.Use(middleware.Logger)
	}