github.com/solo-io/cue@v0.4.7/pkg/tool/http/http.go (about) 1 // Copyright 2019 CUE Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package http 16 17 //go:generate go run gen.go 18 //go:generate gofmt -s -w . 19 20 import ( 21 "bytes" 22 "io" 23 "io/ioutil" 24 "net/http" 25 26 "github.com/solo-io/cue/cue" 27 "github.com/solo-io/cue/internal/task" 28 ) 29 30 func init() { 31 task.Register("tool/http.Do", newHTTPCmd) 32 33 // For backwards compatibility. 34 task.Register("http", newHTTPCmd) 35 } 36 37 type httpCmd struct{} 38 39 func newHTTPCmd(v cue.Value) (task.Runner, error) { 40 return &httpCmd{}, nil 41 } 42 43 func (c *httpCmd) Run(ctx *task.Context) (res interface{}, err error) { 44 var header, trailer http.Header 45 var ( 46 method = ctx.String("method") 47 u = ctx.String("url") 48 ) 49 var r io.Reader 50 if obj := ctx.Obj.Lookup("request"); obj.Exists() { 51 if v := obj.Lookup("body"); v.Exists() { 52 r, err = v.Reader() 53 if err != nil { 54 return nil, err 55 } 56 } else { 57 r = bytes.NewReader([]byte("")) 58 } 59 if header, err = parseHeaders(obj, "header"); err != nil { 60 return nil, err 61 } 62 if trailer, err = parseHeaders(obj, "trailer"); err != nil { 63 return nil, err 64 } 65 } 66 if ctx.Err != nil { 67 return nil, ctx.Err 68 } 69 70 req, err := http.NewRequest(method, u, r) 71 if err != nil { 72 return nil, err 73 } 74 req.Header = header 75 req.Trailer = trailer 76 77 // TODO: 78 // - retry logic 79 // - TLS certs 80 resp, err := http.DefaultClient.Do(req) 81 if err != nil { 82 return nil, err 83 } 84 defer resp.Body.Close() 85 b, err := ioutil.ReadAll(resp.Body) 86 // parse response body and headers 87 return map[string]interface{}{ 88 "response": map[string]interface{}{ 89 "status": resp.Status, 90 "statusCode": resp.StatusCode, 91 "body": string(b), 92 "header": resp.Header, 93 "trailer": resp.Trailer, 94 }, 95 }, err 96 } 97 98 func parseHeaders(obj cue.Value, label string) (http.Header, error) { 99 m := obj.Lookup(label) 100 if !m.Exists() { 101 return nil, nil 102 } 103 iter, err := m.Fields() 104 if err != nil { 105 return nil, err 106 } 107 h := http.Header{} 108 for iter.Next() { 109 str, err := iter.Value().String() 110 if err != nil { 111 return nil, err 112 } 113 h.Add(iter.Label(), str) 114 } 115 return h, nil 116 }