package util import ( "net/http" "strings" ) // ApplyCustomHeadersFromAttrs applies user-defined headers stored in the provided attributes map. // Custom headers override built-in defaults when conflicts occur. func ApplyCustomHeadersFromAttrs(r *http.Request, attrs map[string]string) { if r == nil { return } applyCustomHeaders(r, extractCustomHeaders(attrs)) } func extractCustomHeaders(attrs map[string]string) map[string]string { if len(attrs) == 0 { return nil } headers := make(map[string]string) for k, v := range attrs { if !strings.HasPrefix(k, "header:") { continue } name := strings.TrimSpace(strings.TrimPrefix(k, "header:")) if name == "" { continue } val := strings.TrimSpace(v) if val == "" { continue } headers[name] = val } if len(headers) == 0 { return nil } return headers } func applyCustomHeaders(r *http.Request, headers map[string]string) { if r == nil || len(headers) == 0 { return } for k, v := range headers { if k == "" || v == "" { continue } // Host is read from req.Host (not req.Header) by net/http when // writing the request; setting it via Header.Set is silently // dropped on the wire. Handle it explicitly so user-configured // virtual-host overrides actually take effect upstream. if http.CanonicalHeaderKey(k) == "Host" { r.Host = v continue } r.Header.Set(k, v) } }