mirror of
				https://github.com/traefik/traefik.git
				synced 2025-11-04 02:11:15 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			65 lines
		
	
	
		
			1.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			65 lines
		
	
	
		
			1.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package denyrouterrecursion
 | 
						|
 | 
						|
import (
 | 
						|
	"errors"
 | 
						|
	"hash/fnv"
 | 
						|
	"net/http"
 | 
						|
	"strconv"
 | 
						|
 | 
						|
	"github.com/containous/alice"
 | 
						|
	"github.com/rs/zerolog/log"
 | 
						|
	"github.com/traefik/traefik/v3/pkg/logs"
 | 
						|
)
 | 
						|
 | 
						|
const xTraefikRouter = "X-Traefik-Router"
 | 
						|
 | 
						|
type DenyRouterRecursion struct {
 | 
						|
	routerName     string
 | 
						|
	routerNameHash string
 | 
						|
	next           http.Handler
 | 
						|
}
 | 
						|
 | 
						|
// WrapHandler Wraps router to alice.Constructor.
 | 
						|
func WrapHandler(routerName string) alice.Constructor {
 | 
						|
	return func(next http.Handler) (http.Handler, error) {
 | 
						|
		return New(routerName, next)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// New creates a new DenyRouterRecursion.
 | 
						|
// DenyRouterRecursion middleware is an internal middleware used to avoid infinite requests loop on the same router.
 | 
						|
func New(routerName string, next http.Handler) (*DenyRouterRecursion, error) {
 | 
						|
	if routerName == "" {
 | 
						|
		return nil, errors.New("routerName cannot be empty")
 | 
						|
	}
 | 
						|
 | 
						|
	return &DenyRouterRecursion{
 | 
						|
		routerName:     routerName,
 | 
						|
		routerNameHash: makeHash(routerName),
 | 
						|
		next:           next,
 | 
						|
	}, nil
 | 
						|
}
 | 
						|
 | 
						|
// ServeHTTP implements http.Handler.
 | 
						|
func (l *DenyRouterRecursion) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
 | 
						|
	if req.Header.Get(xTraefikRouter) == l.routerNameHash {
 | 
						|
		logger := log.With().Str(logs.MiddlewareType, "DenyRouterRecursion").Logger()
 | 
						|
		logger.Debug().Msgf("Rejecting request in provenance of the same router (%q) to stop potential infinite loop.", l.routerName)
 | 
						|
 | 
						|
		rw.WriteHeader(http.StatusBadRequest)
 | 
						|
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	req.Header.Set(xTraefikRouter, l.routerNameHash)
 | 
						|
 | 
						|
	l.next.ServeHTTP(rw, req)
 | 
						|
}
 | 
						|
 | 
						|
func makeHash(routerName string) string {
 | 
						|
	hasher := fnv.New64()
 | 
						|
	// purposely ignoring the error, as no error can be returned from the implementation.
 | 
						|
	_, _ = hasher.Write([]byte(routerName))
 | 
						|
	return strconv.FormatUint(hasher.Sum64(), 16)
 | 
						|
}
 |