github.com/akamai/AkamaiOPEN-edgegrid-golang/v8@v8.1.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.Header.Get("Accept") == "" { 46 r.Header.Set("Accept", "application/json") 47 } 48 49 if r.URL.Scheme == "" { 50 r.URL.Scheme = "https" 51 } 52 53 if len(in) > 0 { 54 data, err := json.Marshal(in[0]) 55 if err != nil { 56 return nil, fmt.Errorf("%w: %s", ErrMarshaling, err) 57 } 58 59 r.Body = ioutil.NopCloser(bytes.NewBuffer(data)) 60 r.ContentLength = int64(len(data)) 61 } 62 63 s.client.CheckRedirect = func(req *http.Request, via []*http.Request) error { 64 return s.Sign(req) 65 } 66 67 if err := s.Sign(r); err != nil { 68 return nil, err 69 } 70 71 if s.trace { 72 data, err := httputil.DumpRequestOut(r, true) 73 if err != nil { 74 log.WithError(err).Error("Failed to dump request") 75 } else { 76 log.Debug(string(data)) 77 } 78 } 79 80 resp, err := s.client.Do(r) 81 if err != nil { 82 return nil, err 83 } 84 85 if s.trace { 86 data, err := httputil.DumpResponse(resp, true) 87 if err != nil { 88 log.WithError(err).Error("Failed to dump response") 89 } else { 90 log.Debug(string(data)) 91 } 92 } 93 94 if out != nil && 95 resp.StatusCode >= http.StatusOK && resp.StatusCode < http.StatusMultipleChoices && 96 resp.StatusCode != http.StatusNoContent && resp.StatusCode != http.StatusResetContent { 97 data, err := ioutil.ReadAll(resp.Body) 98 if err != nil { 99 return nil, err 100 } 101 resp.Body = ioutil.NopCloser(bytes.NewBuffer(data)) 102 103 if err := json.Unmarshal(data, out); err != nil { 104 return nil, fmt.Errorf("%w: %s", ErrUnmarshaling, err) 105 } 106 } 107 108 return resp, nil 109 } 110 111 // Sign will only sign a request 112 func (s *session) Sign(r *http.Request) error { 113 s.signer.SignRequest(r) 114 115 if s.requestLimit != 0 { 116 s.signer.CheckRequestLimit(s.requestLimit) 117 } 118 return nil 119 }