summaryrefslogtreecommitdiff
path: root/data/datasource_http.go
diff options
context:
space:
mode:
authorDave Henderson <dhenderson@gmail.com>2018-12-03 21:32:43 -0500
committerGitHub <noreply@github.com>2018-12-03 21:32:43 -0500
commitd97981ecc9929df01da0cce6cbbcea940202f643 (patch)
tree80eebe0c78694a9feb00db3fdb0769eee8d2f008 /data/datasource_http.go
parent2f357bd5a55169452deeebfaccab6515b06364de (diff)
Support subpaths for http datasources (#442)
* bug: subpaths were ignored in http datasources Signed-off-by: Dave Henderson <dhenderson@gmail.com> * fixup! bug: subpaths were ignored in http datasources
Diffstat (limited to 'data/datasource_http.go')
-rw-r--r--data/datasource_http.go100
1 files changed, 100 insertions, 0 deletions
diff --git a/data/datasource_http.go b/data/datasource_http.go
new file mode 100644
index 00000000..5424fbd0
--- /dev/null
+++ b/data/datasource_http.go
@@ -0,0 +1,100 @@
+package data
+
+import (
+ "io/ioutil"
+ "mime"
+ "net/http"
+ "net/url"
+ "strings"
+ "time"
+
+ "github.com/pkg/errors"
+)
+
+func buildURL(base *url.URL, args ...string) (*url.URL, error) {
+ if len(args) == 0 {
+ return base, nil
+ }
+ p, err := url.Parse(args[0])
+ if err != nil {
+ return nil, errors.Wrapf(err, "bad sub-path %s", args[0])
+ }
+ return base.ResolveReference(p), nil
+}
+
+func readHTTP(source *Source, args ...string) ([]byte, error) {
+ if source.hc == nil {
+ source.hc = &http.Client{Timeout: time.Second * 5}
+ }
+ u, err := buildURL(source.URL, args...)
+ if err != nil {
+ return nil, err
+ }
+ req, err := http.NewRequest("GET", u.String(), nil)
+ if err != nil {
+ return nil, err
+ }
+ req.Header = source.header
+ res, err := source.hc.Do(req)
+ if err != nil {
+ return nil, err
+ }
+ body, err := ioutil.ReadAll(res.Body)
+ if err != nil {
+ return nil, err
+ }
+ err = res.Body.Close()
+ if err != nil {
+ return nil, err
+ }
+ if res.StatusCode != 200 {
+ err := errors.Errorf("Unexpected HTTP status %d on GET from %s: %s", res.StatusCode, source.URL, string(body))
+ return nil, err
+ }
+ ctypeHdr := res.Header.Get("Content-Type")
+ if ctypeHdr != "" {
+ mediatype, _, e := mime.ParseMediaType(ctypeHdr)
+ if e != nil {
+ return nil, e
+ }
+ source.mediaType = mediatype
+ }
+ return body, nil
+}
+
+func parseHeaderArgs(headerArgs []string) (map[string]http.Header, error) {
+ headers := make(map[string]http.Header)
+ for _, v := range headerArgs {
+ ds, name, value, err := splitHeaderArg(v)
+ if err != nil {
+ return nil, err
+ }
+ if _, ok := headers[ds]; !ok {
+ headers[ds] = make(http.Header)
+ }
+ headers[ds][name] = append(headers[ds][name], strings.TrimSpace(value))
+ }
+ return headers, nil
+}
+
+func splitHeaderArg(arg string) (datasourceAlias, name, value string, err error) {
+ parts := strings.SplitN(arg, "=", 2)
+ if len(parts) != 2 {
+ err = errors.Errorf("Invalid datasource-header option '%s'", arg)
+ return "", "", "", err
+ }
+ datasourceAlias = parts[0]
+ name, value, err = splitHeader(parts[1])
+ return datasourceAlias, name, value, err
+}
+
+func splitHeader(header string) (name, value string, err error) {
+ parts := strings.SplitN(header, ":", 2)
+ if len(parts) != 2 {
+ err = errors.Errorf("Invalid HTTP Header format '%s'", header)
+ return "", "", err
+ }
+ name = http.CanonicalHeaderKey(parts[0])
+ value = parts[1]
+ return name, value, nil
+}