github.com/akamai/AkamaiOPEN-edgegrid-golang/v2@v2.17.0/pkg/session/request.go (about) 1 package session 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "errors" 7 "fmt" 8 "io/ioutil" 9 "net/http" 10 "net/http/httputil" 11 ) 12 13 var ( 14 // ErrInvalidArgument is returned when invalid number of arguments were supplied to a function 15 ErrInvalidArgument = errors.New("invalid arguments provided") 16 // ErrMarshaling represents marshaling error 17 ErrMarshaling = errors.New("marshaling input") 18 // ErrUnmarshaling represents unmarshaling error 19 ErrUnmarshaling = errors.New("unmarshaling output") 20 ) 21 22 // Exec will sign and execute the request using the client edgegrid.Config 23 func (s *session) Exec(r *http.Request, out interface{}, in ...interface{}) (*http.Response, error) { 24 if len(in) > 1 { 25 return nil, fmt.Errorf("%w: %s", ErrInvalidArgument, "'in' argument must have 0 or 1 value") 26 } 27 log := s.Log(r.Context()) 28 29 // Apply any context header overrides 30 if o, ok := r.Context().Value(contextOptionKey).(*contextOptions); ok { 31 for k, v := range o.header { 32 r.Header[k] = v 33 } 34 } 35 36 r.URL.RawQuery = r.URL.Query().Encode() 37 if r.UserAgent() == "" { 38 r.Header.Set("User-Agent", s.userAgent) 39 } 40 41 if r.Header.Get("Content-Type") == "" { 42 r.Header.Set("Content-Type", "application/json") 43 } 44 45 if r.URL.Scheme == "" { 46 r.URL.Scheme = "https" 47 } 48 49 if len(in) > 0 { 50 data, err := json.Marshal(in[0]) 51 if err != nil { 52 return nil, fmt.Errorf("%w: %s", ErrMarshaling, err) 53 } 54 55 r.Body = ioutil.NopCloser(bytes.NewBuffer(data)) 56 r.ContentLength = int64(len(data)) 57 } 58 59 s.client.CheckRedirect = func(req *http.Request, via []*http.Request) error { 60 return s.Sign(req) 61 } 62 63 if err := s.Sign(r); err != nil { 64 return nil, err 65 } 66 67 if s.trace { 68 data, err := httputil.DumpRequestOut(r, true) 69 if err != nil { 70 log.WithError(err).Error("Failed to dump request") 71 } else { 72 log.Debug(string(data)) 73 } 74 } 75 76 resp, err := s.client.Do(r) 77 if err != nil { 78 return nil, err 79 } 80 81 if s.trace { 82 data, err := httputil.DumpResponse(resp, true) 83 if err != nil { 84 log.WithError(err).Error("Failed to dump response") 85 } else { 86 log.Debug(string(data)) 87 } 88 } 89 90 if out != nil && 91 resp.StatusCode >= http.StatusOK && resp.StatusCode < http.StatusMultipleChoices && 92 resp.StatusCode != http.StatusNoContent && resp.StatusCode != http.StatusResetContent { 93 data, err := ioutil.ReadAll(resp.Body) 94 resp.Body = ioutil.NopCloser(bytes.NewBuffer(data)) 95 if err != nil { 96 return nil, err 97 } 98 99 if err := json.Unmarshal(data, out); err != nil { 100 return nil, fmt.Errorf("%w: %s", ErrUnmarshaling, err) 101 } 102 } 103 104 return resp, nil 105 } 106 107 // Sign will only sign a request 108 func (s *session) Sign(r *http.Request) error { 109 s.signer.SignRequest(r) 110 return nil 111 }