github.com/qiniu/go-sdk/v7@v7.27.0/internal/clientv2/request_compatible.go (about) 1 package clientv2 2 3 import ( 4 "mime/multipart" 5 "net/http" 6 "net/textproto" 7 "net/url" 8 ) 9 10 // 此处是为了版本兼容,sdk 支持最低版本为 go1.10, go1.13 提供 req.Clone 方法, 11 // 此处 copy 高版本的 go 标准库方法 12 func cloneReq(r *http.Request) *http.Request { 13 r2 := r.WithContext(r.Context()) 14 if r.Header != nil { 15 r2.Header = cloneHeader(r.Header) 16 } 17 if r.Trailer != nil { 18 r2.Trailer = cloneHeader(r.Trailer) 19 } 20 if s := r.TransferEncoding; s != nil { 21 s2 := make([]string, len(s)) 22 copy(s2, s) 23 r2.TransferEncoding = s2 24 } 25 r2.Form = cloneURLValues(r.Form) 26 r2.PostForm = cloneURLValues(r.PostForm) 27 r2.MultipartForm = cloneMultipartForm(r.MultipartForm) 28 return r2 29 } 30 31 func cloneHeader(h http.Header) http.Header { 32 if h == nil { 33 return nil 34 } 35 36 // Find total number of values. 37 nv := 0 38 for _, vv := range h { 39 nv += len(vv) 40 } 41 sv := make([]string, nv) // shared backing array for headers' values 42 h2 := make(http.Header, len(h)) 43 for k, vv := range h { 44 n := copy(sv, vv) 45 h2[k] = sv[:n:n] 46 sv = sv[n:] 47 } 48 return h2 49 } 50 51 func cloneURLValues(v url.Values) url.Values { 52 if v == nil { 53 return nil 54 } 55 56 // http.Header and url.Values have the same representation, so temporarily 57 // treat it like http.Header, which does have a clone: 58 return url.Values(cloneHeader(http.Header(v))) 59 } 60 61 func cloneMultipartForm(f *multipart.Form) *multipart.Form { 62 if f == nil { 63 return nil 64 } 65 f2 := &multipart.Form{ 66 Value: (map[string][]string)(cloneHeader(http.Header(f.Value))), 67 } 68 if f.File != nil { 69 m := make(map[string][]*multipart.FileHeader) 70 for k, vv := range f.File { 71 vv2 := make([]*multipart.FileHeader, len(vv)) 72 for i, v := range vv { 73 vv2[i] = cloneMultipartFileHeader(v) 74 } 75 m[k] = vv2 76 } 77 f2.File = m 78 } 79 return f2 80 } 81 82 func cloneMultipartFileHeader(fh *multipart.FileHeader) *multipart.FileHeader { 83 if fh == nil { 84 return nil 85 } 86 fh2 := new(multipart.FileHeader) 87 *fh2 = *fh 88 fh2.Header = textproto.MIMEHeader(cloneHeader(http.Header(fh.Header))) 89 return fh2 90 }