Ctrl K
ComunidadGuías…

pkg/prom/header_patch.go

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
package prom

import (
	"errors"
	"maps"
	"net/http"
	"strings"

	"github.com/skyhook-io/radar/pkg/urlutil"
)

type HeaderOperation struct {
	Key    string `json:"key"`
	Action string `json:"action"`
	Value  string `json:"value,omitempty"`
}

func ApplyHeaderOperations(original Connection, targetURL string, operations []HeaderOperation) (Connection, error) {
	result := Connection{URL: targetURL, Headers: maps.Clone(original.Headers), HeadersFromEnv: maps.Clone(original.HeadersFromEnv)}
	if result.Headers == nil {
		result.Headers = map[string]string{}
	}
	seen := map[string]bool{}
	preserved := map[string]bool{}
	for key := range original.Headers {
		preserved[strings.ToLower(key)] = true
	}
	for key := range original.HeadersFromEnv {
		preserved[strings.ToLower(key)] = true
	}
	for _, op := range operations {
		key := strings.TrimSpace(op.Key)
		lower := strings.ToLower(key)
		if key == "" || seen[lower] {
			return Connection{}, errors.New("header operations require unique header names")
		}
		seen[lower] = true
		if err := ValidateHeaders(map[string]string{key: ""}); err != nil {
			return Connection{}, err
		}
		for envKey := range original.HeadersFromEnv {
			if strings.EqualFold(envKey, key) && op.Action != "keep" {
				return Connection{}, errors.New("environment-backed headers must be edited in clusters.json")
			}
		}
		switch op.Action {
		case "keep":
			if !preserved[lower] || op.Value != "" {
				return Connection{}, errors.New("keep requires a saved header and no value")
			}
		case "set", "clear":
			if op.Action == "clear" && op.Value != "" {
				return Connection{}, errors.New("clear must not include a header value")
			}
			delete(preserved, lower)
			for oldKey := range result.Headers {
				if strings.EqualFold(oldKey, key) {
					delete(result.Headers, oldKey)
				}
			}
			if op.Action == "set" {
				result.Headers[http.CanonicalHeaderKey(key)] = op.Value
			}
		default:
			return Connection{}, errors.New("header action must be keep, set, or clear")
		}
	}
	if len(preserved) > 0 {
		before, ok := urlutil.NormalizeOrigin(original.URL)
		after, valid := urlutil.NormalizeOrigin(targetURL)
		if !ok || !valid || before != after {
			message := "changing servers requires replacing or clearing every saved header"
			if len(original.HeadersFromEnv) > 0 {
				message += "; edit environment references in clusters.json"
			}
			return Connection{}, errors.New(message)
		}
	}
	if err := result.Validate(); err != nil {
		return Connection{}, err
	}
	return result, nil
}