| // Copyright 2019 The Go Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style | |
| // license that can be found in the LICENSE file. | |
| package http | |
| import ( | |
| "mime/multipart" | |
| "net/textproto" | |
| "net/url" | |
| _ "unsafe" // for linkname | |
| ) | |
| // cloneURLValues should be an internal detail, | |
| // but widely used packages access it using linkname. | |
| // Notable members of the hall of shame include: | |
| // - github.com/searKing/golang | |
| // | |
| // Do not remove or change the type signature. | |
| // See go.dev/issue/67401. | |
| // | |
| //go:linkname cloneURLValues | |
| func cloneURLValues(v url.Values) url.Values { | |
| if v == nil { | |
| return nil | |
| } | |
| // http.Header and url.Values have the same representation, so temporarily | |
| // treat it like http.Header, which does have a clone: | |
| return url.Values(Header(v).Clone()) | |
| } | |
| // cloneURL should be an internal detail, | |
| // but widely used packages access it using linkname. | |
| // Notable members of the hall of shame include: | |
| // - github.com/searKing/golang | |
| // | |
| // Do not remove or change the type signature. | |
| // See go.dev/issue/67401. | |
| // | |
| //go:linkname cloneURL | |
| func cloneURL(u *url.URL) *url.URL { | |
| if u == nil { | |
| return nil | |
| } | |
| u2 := new(url.URL) | |
| *u2 = *u | |
| if u.User != nil { | |
| u2.User = new(url.Userinfo) | |
| *u2.User = *u.User | |
| } | |
| return u2 | |
| } | |
| // cloneMultipartForm should be an internal detail, | |
| // but widely used packages access it using linkname. | |
| // Notable members of the hall of shame include: | |
| // - github.com/searKing/golang | |
| // | |
| // Do not remove or change the type signature. | |
| // See go.dev/issue/67401. | |
| // | |
| //go:linkname cloneMultipartForm | |
| func cloneMultipartForm(f *multipart.Form) *multipart.Form { | |
| if f == nil { | |
| return nil | |
| } | |
| f2 := &multipart.Form{ | |
| Value: (map[string][]string)(Header(f.Value).Clone()), | |
| } | |
| if f.File != nil { | |
| m := make(map[string][]*multipart.FileHeader, len(f.File)) | |
| for k, vv := range f.File { | |
| vv2 := make([]*multipart.FileHeader, len(vv)) | |
| for i, v := range vv { | |
| vv2[i] = cloneMultipartFileHeader(v) | |
| } | |
| m[k] = vv2 | |
| } | |
| f2.File = m | |
| } | |
| return f2 | |
| } | |
| // cloneMultipartFileHeader should be an internal detail, | |
| // but widely used packages access it using linkname. | |
| // Notable members of the hall of shame include: | |
| // - github.com/searKing/golang | |
| // | |
| // Do not remove or change the type signature. | |
| // See go.dev/issue/67401. | |
| // | |
| //go:linkname cloneMultipartFileHeader | |
| func cloneMultipartFileHeader(fh *multipart.FileHeader) *multipart.FileHeader { | |
| if fh == nil { | |
| return nil | |
| } | |
| fh2 := new(multipart.FileHeader) | |
| *fh2 = *fh | |
| fh2.Header = textproto.MIMEHeader(Header(fh.Header).Clone()) | |
| return fh2 | |
| } | |
| // cloneOrMakeHeader invokes Header.Clone but if the | |
| // result is nil, it'll instead make and return a non-nil Header. | |
| // | |
| // cloneOrMakeHeader should be an internal detail, | |
| // but widely used packages access it using linkname. | |
| // Notable members of the hall of shame include: | |
| // - github.com/searKing/golang | |
| // | |
| // Do not remove or change the type signature. | |
| // See go.dev/issue/67401. | |
| // | |
| //go:linkname cloneOrMakeHeader | |
| func cloneOrMakeHeader(hdr Header) Header { | |
| clone := hdr.Clone() | |
| if clone == nil { | |
| clone = make(Header) | |
| } | |
| return clone | |
| } | |