<commit_before>package aggregation

import (
	"context"
	"net/http"
	"regexp"
	"sort"
	"sync"
	"time"

	"github.com/gorilla/mux"
	v3 "github.com/rancher/rancher/pkg/apis/management.cattle.io/v3"
	mgmtcontrollers "github.com/rancher/rancher/pkg/generated/controllers/management.cattle.io/v3"
	"github.com/rancher/remotedialer"
	"github.com/rancher/steve/pkg/proxy"
	"github.com/rancher/wrangler/pkg/relatedresource"
	"k8s.io/apimachinery/pkg/labels"
	"k8s.io/client-go/rest"
)

var (
	clusterPrefixRegexp = regexp.MustCompile(`^/k8s/clusters/[^/]+`)
)

type aggregationHandler struct {
	sync.Mutex

	apiServiceCache mgmtcontrollers.APIServiceCache
	mux             *mux.Router
	remote          *remotedialer.Server
}

type routeEntry struct {
	path   string
	prefix string
	uuid   string
}

func NewMiddleware(ctx context.Context, apiServices mgmtcontrollers.APIServiceController, remotedialer *remotedialer.Server) func(http.Handler) http.Handler {
	handler := &aggregationHandler{
		apiServiceCache: apiServices.Cache(),
		remote:          remotedialer,
	}
	relatedresource.WatchClusterScoped(ctx, "aggregation-router", relatedresource.TriggerAllKey,
		apiServices, apiServices)
	apiServices.OnChange(ctx, "apiservice-router", handler.OnChange)
	return handler.Middleware
}

func (h *aggregationHandler) Middleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
		h.next(next).ServeHTTP(rw, req)
	})
}

func (h *aggregationHandler) next(notFound http.Handler) http.Handler {
	h.Lock()
	defer h.Unlock()
	if h.mux == nil {
		return notFound
	}
	h.mux.NotFoundHandler = notFound
	return h.mux
}

func (h *aggregationHandler) setEntries(routes []routeEntry) {
	mux := mux.NewRouter()
	for _, entry := range routes {<commit_msg>Fix API redirect for paths with multiple %2F (fwd slash)<commit_after>package aggregation

import (
	"context"
	"net/http"
	"regexp"
	"sort"
	"sync"
	"time"

	"github.com/gorilla/mux"
	v3 "github.com/rancher/rancher/pkg/apis/management.cattle.io/v3"
	mgmtcontrollers "github.com/rancher/rancher/pkg/generated/controllers/management.cattle.io/v3"
	"github.com/rancher/remotedialer"
	"github.com/rancher/steve/pkg/proxy"
	"github.com/rancher/wrangler/pkg/relatedresource"
	"k8s.io/apimachinery/pkg/labels"
	"k8s.io/client-go/rest"
)

var (
	clusterPrefixRegexp = regexp.MustCompile(`^/k8s/clusters/[^/]+`)
)

type aggregationHandler struct {
	sync.Mutex

	apiServiceCache mgmtcontrollers.APIServiceCache
	mux             *mux.Router
	remote          *remotedialer.Server
}

type routeEntry struct {
	path   string
	prefix string
	uuid   string
}

func NewMiddleware(ctx context.Context, apiServices mgmtcontrollers.APIServiceController, remotedialer *remotedialer.Server) func(http.Handler) http.Handler {
	handler := &aggregationHandler{
		apiServiceCache: apiServices.Cache(),
		remote:          remotedialer,
	}
	relatedresource.WatchClusterScoped(ctx, "aggregation-router", relatedresource.TriggerAllKey,
		apiServices, apiServices)
	apiServices.OnChange(ctx, "apiservice-router", handler.OnChange)
	return handler.Middleware
}

func (h *aggregationHandler) Middleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
		h.next(next).ServeHTTP(rw, req)
	})
}

func (h *aggregationHandler) next(notFound http.Handler) http.Handler {
	h.Lock()
	defer h.Unlock()
	if h.mux == nil {
		return notFound
	}
	h.mux.NotFoundHandler = notFound
	return h.mux
}

func (h *aggregationHandler) setEntries(routes []routeEntry) {
	mux := mux.NewRouter()
	mux.UseEncodedPath()
	for _, entry := range routes {
{'fraction_non_alphanumeric': 0.12201154163231658, 'fraction_numerical': 0.003572410002748008, 'mean_word_length': 4.786963434022257, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2387839', 'n_tokens_mistral': 1311, 'n_tokens_neox': 1292, 'n_words': 226}