mirror of
https://github.com/golang/go
synced 2024-11-17 14:04:48 -07:00
net/http: export Header.Clone, reduce its allocations, use it everywhere
Fixes #29915 Change-Id: I6e6edf4f9a0e062211f74d120ae1a242bce1b274 Reviewed-on: https://go-review.googlesource.com/c/go/+/173658 Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Ingo Oeser <nightlyone@googlemail.com> Reviewed-by: Benny Siegert <bsiegert@gmail.com>
This commit is contained in:
parent
2417b0d006
commit
13d0af4e70
@ -238,7 +238,7 @@ func send(ireq *Request, rt RoundTripper, deadline time.Time) (resp *Response, d
|
||||
username := u.Username()
|
||||
password, _ := u.Password()
|
||||
forkReq()
|
||||
req.Header = ireq.Header.clone()
|
||||
req.Header = ireq.Header.Clone()
|
||||
req.Header.Set("Authorization", "Basic "+basicAuth(username, password))
|
||||
}
|
||||
|
||||
@ -668,7 +668,7 @@ func (c *Client) makeHeadersCopier(ireq *Request) func(*Request) {
|
||||
// The headers to copy are from the very initial request.
|
||||
// We use a closured callback to keep a reference to these original headers.
|
||||
var (
|
||||
ireqhdr = ireq.Header.clone()
|
||||
ireqhdr = ireq.Header.Clone()
|
||||
icookies map[string][]*Cookie
|
||||
)
|
||||
if c.Jar != nil && ireq.Header.Get("Cookie") != "" {
|
||||
|
@ -78,12 +78,19 @@ func (h Header) write(w io.Writer, trace *httptrace.ClientTrace) error {
|
||||
return h.writeSubset(w, nil, trace)
|
||||
}
|
||||
|
||||
func (h Header) clone() Header {
|
||||
// Clone returns a copy of h.
|
||||
func (h Header) Clone() Header {
|
||||
// Find total number of values.
|
||||
nv := 0
|
||||
for _, vv := range h {
|
||||
nv += len(vv)
|
||||
}
|
||||
sv := make([]string, nv) // shared backing array for headers' values
|
||||
h2 := make(Header, len(h))
|
||||
for k, vv := range h {
|
||||
vv2 := make([]string, len(vv))
|
||||
copy(vv2, vv)
|
||||
h2[k] = vv2
|
||||
n := copy(sv, vv)
|
||||
h2[k] = sv[:n:n]
|
||||
sv = sv[n:]
|
||||
}
|
||||
return h2
|
||||
}
|
||||
|
@ -127,17 +127,7 @@ func (rw *ResponseRecorder) WriteHeader(code int) {
|
||||
if rw.HeaderMap == nil {
|
||||
rw.HeaderMap = make(http.Header)
|
||||
}
|
||||
rw.snapHeader = cloneHeader(rw.HeaderMap)
|
||||
}
|
||||
|
||||
func cloneHeader(h http.Header) http.Header {
|
||||
h2 := make(http.Header, len(h))
|
||||
for k, vv := range h {
|
||||
vv2 := make([]string, len(vv))
|
||||
copy(vv2, vv)
|
||||
h2[k] = vv2
|
||||
}
|
||||
return h2
|
||||
rw.snapHeader = rw.HeaderMap.Clone()
|
||||
}
|
||||
|
||||
// Flush sets rw.Flushed to true.
|
||||
@ -168,7 +158,7 @@ func (rw *ResponseRecorder) Result() *http.Response {
|
||||
return rw.result
|
||||
}
|
||||
if rw.snapHeader == nil {
|
||||
rw.snapHeader = cloneHeader(rw.HeaderMap)
|
||||
rw.snapHeader = rw.HeaderMap.Clone()
|
||||
}
|
||||
res := &http.Response{
|
||||
Proto: "HTTP/1.1",
|
||||
|
@ -132,16 +132,6 @@ func copyHeader(dst, src http.Header) {
|
||||
}
|
||||
}
|
||||
|
||||
func cloneHeader(h http.Header) http.Header {
|
||||
h2 := make(http.Header, len(h))
|
||||
for k, vv := range h {
|
||||
vv2 := make([]string, len(vv))
|
||||
copy(vv2, vv)
|
||||
h2[k] = vv2
|
||||
}
|
||||
return h2
|
||||
}
|
||||
|
||||
// Hop-by-hop headers. These are removed when sent to the backend.
|
||||
// As of RFC 7230, hop-by-hop headers are required to appear in the
|
||||
// Connection header field. These are the headers defined by the
|
||||
@ -211,7 +201,7 @@ func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||
outreq.Body = nil // Issue 16036: nil Body for http.Transport retries
|
||||
}
|
||||
|
||||
outreq.Header = cloneHeader(req.Header)
|
||||
outreq.Header = req.Header.Clone()
|
||||
|
||||
p.Director(outreq)
|
||||
outreq.Close = false
|
||||
|
@ -1058,7 +1058,7 @@ func (w *response) Header() Header {
|
||||
// Accessing the header between logically writing it
|
||||
// and physically writing it means we need to allocate
|
||||
// a clone to snapshot the logically written state.
|
||||
w.cw.header = w.handlerHeader.clone()
|
||||
w.cw.header = w.handlerHeader.Clone()
|
||||
}
|
||||
w.calledHeader = true
|
||||
return w.handlerHeader
|
||||
@ -1127,7 +1127,7 @@ func (w *response) WriteHeader(code int) {
|
||||
w.status = code
|
||||
|
||||
if w.calledHeader && w.cw.header == nil {
|
||||
w.cw.header = w.handlerHeader.clone()
|
||||
w.cw.header = w.handlerHeader.Clone()
|
||||
}
|
||||
|
||||
if cl := w.handlerHeader.get("Content-Length"); cl != "" {
|
||||
|
Loading…
Reference in New Issue
Block a user