mirror of
				https://github.com/traefik/traefik.git
				synced 2025-10-31 00:11:38 +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/observability/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)
 | |
| }
 |