How to augment the map returned by a ResponseWriter's Header()

Viewed 82

So I'm sure I'm trying to cheat here, but the ResponseWriter docs has a method 'Header()' which returns the Header object it's using. https://pkg.go.dev/net/http#ResponseWriter.Header

Now I'm getting a http.Response from somewhere else, and I want to copy across all the headers from that into my ResponseWriter.

Now, I could use a for loop like this:

for k := range resp.Header 
    w.Header().Add(k, resp.Header.Get(k))
}

Logically, it also made sense for me to just change the reference from the ResponseWriter's header, to the Response's header, however it seems like the ResponseWriter type is actively trying to stop me from doing that.

Something stupid like this comes to mind

w.Header() = resp.Header

Or

rwHeader := w.Header()
rwHeader = resp.Header

Obviously both of these make no sense and do not work at all, but hopefully conveys the idea of what I'm trying to do.

Can anyone offer an explanation of why what I'm trying to do doesn't work? Or maybe it does and I'm just not seeing the way to do it?

2 Answers

You don't have to write that loop yourself. Go 1.18 saw the addition of package golang.org/x/exp/maps, which provides a convenient Copy function:

func Copy[M ~map[K]V, K comparable, V any](dst, src M)

Copy copies all key/value pairs in src adding them to dst. When a key in src is already present in dst, the value in dst will be overwritten by the value associated with the key in src.

import "golang.org/x/exp/maps"
// ...
maps.Copy(w.Header(), resp.Header)

However, note that, because a response can contain duplicate headers, the use of maps.Copy isn't exactly equivalent to your loop:

for k := range resp.Header 
    w.Header().Add(k, resp.Header.Get(k))
}

Contrary to maps.Copy, your loop retrieves only the first header value corresponding to each header name present in resp.Header.

You can't.

w is an http.ResponseWriter which is an interface type - so only has methods and no directly accessible fields. It has, as you know, a method to get the underlying Header map.

It does not, however, have a "Setter" method to replace the map. So the only way to copy over header values is by hand like your cited loop does.

Related