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 } // net/http reads Host from req.Host (not req.Header) when writing // a real request, so we must mirror it there. Some callers pass // synthetic requests (e.g. &http.Request{Header: ...}) and only // consume r.Header afterwards, so keep the value in the header // map too. if http.CanonicalHeaderKey(k) == "Host" { r.Host = v } r.Header.Set(k, v) } }