github.com/wuhuizuo/gomplate@v3.5.0+incompatible/data/datasource_http.go (about) 1 package data 2 3 import ( 4 "io/ioutil" 5 "mime" 6 "net/http" 7 "net/url" 8 "strings" 9 "time" 10 11 "github.com/pkg/errors" 12 ) 13 14 func buildURL(base *url.URL, args ...string) (*url.URL, error) { 15 if len(args) == 0 { 16 return base, nil 17 } 18 p, err := url.Parse(args[0]) 19 if err != nil { 20 return nil, errors.Wrapf(err, "bad sub-path %s", args[0]) 21 } 22 return base.ResolveReference(p), nil 23 } 24 25 func readHTTP(source *Source, args ...string) ([]byte, error) { 26 if source.hc == nil { 27 source.hc = &http.Client{Timeout: time.Second * 5} 28 } 29 u, err := buildURL(source.URL, args...) 30 if err != nil { 31 return nil, err 32 } 33 req, err := http.NewRequest("GET", u.String(), nil) 34 if err != nil { 35 return nil, err 36 } 37 req.Header = source.header 38 res, err := source.hc.Do(req) 39 if err != nil { 40 return nil, err 41 } 42 body, err := ioutil.ReadAll(res.Body) 43 if err != nil { 44 return nil, err 45 } 46 err = res.Body.Close() 47 if err != nil { 48 return nil, err 49 } 50 if res.StatusCode != 200 { 51 err := errors.Errorf("Unexpected HTTP status %d on GET from %s: %s", res.StatusCode, source.URL, string(body)) 52 return nil, err 53 } 54 ctypeHdr := res.Header.Get("Content-Type") 55 if ctypeHdr != "" { 56 mediatype, _, e := mime.ParseMediaType(ctypeHdr) 57 if e != nil { 58 return nil, e 59 } 60 source.mediaType = mediatype 61 } 62 return body, nil 63 } 64 65 func parseHeaderArgs(headerArgs []string) (map[string]http.Header, error) { 66 headers := make(map[string]http.Header) 67 for _, v := range headerArgs { 68 ds, name, value, err := splitHeaderArg(v) 69 if err != nil { 70 return nil, err 71 } 72 if _, ok := headers[ds]; !ok { 73 headers[ds] = make(http.Header) 74 } 75 headers[ds][name] = append(headers[ds][name], strings.TrimSpace(value)) 76 } 77 return headers, nil 78 } 79 80 func splitHeaderArg(arg string) (datasourceAlias, name, value string, err error) { 81 parts := strings.SplitN(arg, "=", 2) 82 if len(parts) != 2 { 83 err = errors.Errorf("Invalid datasource-header option '%s'", arg) 84 return "", "", "", err 85 } 86 datasourceAlias = parts[0] 87 name, value, err = splitHeader(parts[1]) 88 return datasourceAlias, name, value, err 89 } 90 91 func splitHeader(header string) (name, value string, err error) { 92 parts := strings.SplitN(header, ":", 2) 93 if len(parts) != 2 { 94 err = errors.Errorf("Invalid HTTP Header format '%s'", header) 95 return "", "", err 96 } 97 name = http.CanonicalHeaderKey(parts[0]) 98 value = parts[1] 99 return name, value, nil 100 }