1 // Copyright 2019 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4 5 package http
6 7 import (
8 "mime/multipart"
9 "net/textproto"
10 "net/url"
11 _ "unsafe" // for linkname
12 )
13 14 // cloneURLValues should be an internal detail,
15 // but widely used packages access it using linkname.
16 // Notable members of the hall of shame include:
17 // - github.com/searKing/golang
18 //
19 // Do not remove or change the type signature.
20 // See go.dev/issue/67401.
21 //
22 //go:linkname cloneURLValues
23 func cloneURLValues(v url.Values) url.Values {
24 if v == nil {
25 return nil
26 }
27 // http.Header and url.Values have the same representation, so temporarily
28 // treat it like http.Header, which does have a clone:
29 return url.Values(Header(v).Clone())
30 }
31 32 // cloneURL should be an internal detail,
33 // but widely used packages access it using linkname.
34 // Notable members of the hall of shame include:
35 // - github.com/searKing/golang
36 //
37 // Do not remove or change the type signature.
38 // See go.dev/issue/67401.
39 //
40 //go:linkname cloneURL
41 func cloneURL(u *url.URL) *url.URL {
42 if u == nil {
43 return nil
44 }
45 u2 := &url.URL{}
46 *u2 = *u
47 if u.User != nil {
48 u2.User = &url.Userinfo{}
49 *u2.User = *u.User
50 }
51 return u2
52 }
53 54 // cloneMultipartForm should be an internal detail,
55 // but widely used packages access it using linkname.
56 // Notable members of the hall of shame include:
57 // - github.com/searKing/golang
58 //
59 // Do not remove or change the type signature.
60 // See go.dev/issue/67401.
61 //
62 //go:linkname cloneMultipartForm
63 func cloneMultipartForm(f *multipart.Form) *multipart.Form {
64 if f == nil {
65 return nil
66 }
67 f2 := &multipart.Form{
68 Value: (map[string][][]byte)(Header(f.Value).Clone()),
69 }
70 if f.File != nil {
71 m := map[string][]*multipart.FileHeader{}
72 for k, vv := range f.File {
73 vv2 := []*multipart.FileHeader{:len(vv)}
74 for i, v := range vv {
75 vv2[i] = cloneMultipartFileHeader(v)
76 }
77 m[k] = vv2
78 }
79 f2.File = m
80 }
81 return f2
82 }
83 84 // cloneMultipartFileHeader should be an internal detail,
85 // but widely used packages access it using linkname.
86 // Notable members of the hall of shame include:
87 // - github.com/searKing/golang
88 //
89 // Do not remove or change the type signature.
90 // See go.dev/issue/67401.
91 //
92 //go:linkname cloneMultipartFileHeader
93 func cloneMultipartFileHeader(fh *multipart.FileHeader) *multipart.FileHeader {
94 if fh == nil {
95 return nil
96 }
97 fh2 := &multipart.FileHeader{}
98 *fh2 = *fh
99 fh2.Header = textproto.MIMEHeader(Header(fh.Header).Clone())
100 return fh2
101 }
102 103 // cloneOrMakeHeader invokes Header.Clone but if the
104 // result is nil, it'll instead make and return a non-nil Header.
105 //
106 // cloneOrMakeHeader should be an internal detail,
107 // but widely used packages access it using linkname.
108 // Notable members of the hall of shame include:
109 // - github.com/searKing/golang
110 //
111 // Do not remove or change the type signature.
112 // See go.dev/issue/67401.
113 //
114 //go:linkname cloneOrMakeHeader
115 func cloneOrMakeHeader(hdr Header) Header {
116 clone := hdr.Clone()
117 if clone == nil {
118 clone = make(Header)
119 }
120 return clone
121 }
122