github.com/akamai/AkamaiOPEN-edgegrid-golang/v4@v4.1.0/pkg/session/session.go (about) 1 // Package session provides the base secure http client and request management for akamai apis 2 package session 3 4 import ( 5 "context" 6 "net/http" 7 "runtime" 8 "strings" 9 10 "github.com/akamai/AkamaiOPEN-edgegrid-golang/v4/pkg/edgegrid" 11 "github.com/apex/log" 12 "github.com/apex/log/handlers/discard" 13 ) 14 15 type ( 16 // Session is the interface that is used by the pa 17 // This allows the client itself to be more extensible and readily testable, ets. 18 Session interface { 19 // Exec will sign and execute a request returning the response 20 // The response body will be unmarshaled in to out 21 // Optionally the in value will be marshaled into the body 22 Exec(r *http.Request, out interface{}, in ...interface{}) (*http.Response, error) 23 24 // Sign will only sign a request, this is useful for circumstances 25 // when the caller wishes to manage the http client 26 Sign(r *http.Request) error 27 28 // Log returns the logging interface for the session 29 // If provided all debugging will output to this log interface 30 Log(ctx context.Context) log.Interface 31 32 // Client return the session http client 33 Client() *http.Client 34 } 35 36 // session is the base akamai http client 37 session struct { 38 client *http.Client 39 signer edgegrid.Signer 40 log log.Interface 41 trace bool 42 userAgent string 43 } 44 45 contextOptions struct { 46 log log.Interface 47 header http.Header 48 } 49 50 // Option defines a client option 51 Option func(*session) 52 53 contextKey string 54 55 // ContextOption are options on the context 56 ContextOption func(*contextOptions) 57 ) 58 59 var ( 60 contextOptionKey = contextKey("sessionContext") 61 ) 62 63 const ( 64 // Version is the client version 65 Version = "2.0.0" 66 ) 67 68 // New returns a new session 69 func New(opts ...Option) (Session, error) { 70 var ( 71 defaultUserAgent = "Akamai-Open-Edgegrid-golang/" + Version + " golang/" + strings.TrimPrefix(runtime.Version(), "go") 72 ) 73 74 s := &session{ 75 client: http.DefaultClient, 76 log: log.Log, 77 userAgent: defaultUserAgent, 78 trace: false, 79 } 80 81 for _, opt := range opts { 82 opt(s) 83 } 84 85 if s.signer == nil { 86 config, err := edgegrid.New() 87 if err != nil { 88 return nil, err 89 } 90 s.signer = config 91 } 92 93 return s, nil 94 } 95 96 // Must is a helper tthat will result in a panic if an error is returned 97 // ex. sess := Must(New()) 98 func Must(sess Session, err error) Session { 99 if err != nil { 100 panic(err) 101 } 102 103 return sess 104 } 105 106 // WithClient creates a client using the specified http.Client 107 func WithClient(client *http.Client) Option { 108 return func(s *session) { 109 s.client = client 110 } 111 } 112 113 // WithLog sets the log interface for the client 114 func WithLog(l log.Interface) Option { 115 return func(s *session) { 116 s.log = l 117 } 118 } 119 120 // WithUserAgent sets the user agent string for the client 121 func WithUserAgent(u string) Option { 122 return func(s *session) { 123 s.userAgent = u 124 } 125 } 126 127 // WithSigner sets the request signer for the session 128 func WithSigner(signer edgegrid.Signer) Option { 129 return func(s *session) { 130 s.signer = signer 131 } 132 } 133 134 // WithHTTPTracing sets the request and response dump for debugging 135 func WithHTTPTracing(trace bool) Option { 136 return func(s *session) { 137 s.trace = trace 138 } 139 } 140 141 // Log will return the context logger, or the session log 142 func (s *session) Log(ctx context.Context) log.Interface { 143 if o := ctx.Value(contextOptionKey); o != nil { 144 if ops, ok := o.(*contextOptions); ok && ops.log != nil { 145 return ops.log 146 } 147 } 148 if s.log != nil { 149 return s.log 150 } 151 152 return &log.Logger{ 153 Handler: discard.New(), 154 } 155 } 156 157 // Client returns the http client interface 158 func (s *session) Client() *http.Client { 159 return s.client 160 } 161 162 // ContextWithOptions adds request specific options to the context 163 // This log will debug the request only using the provided log 164 func ContextWithOptions(ctx context.Context, opts ...ContextOption) context.Context { 165 o := new(contextOptions) 166 for _, opt := range opts { 167 opt(o) 168 } 169 170 return context.WithValue(ctx, contextOptionKey, o) 171 } 172 173 // WithContextLog provides a context specific logger 174 func WithContextLog(l log.Interface) ContextOption { 175 return func(o *contextOptions) { 176 o.log = l 177 } 178 } 179 180 // WithContextHeaders sets the context headers 181 func WithContextHeaders(h http.Header) ContextOption { 182 return func(o *contextOptions) { 183 o.header = h 184 } 185 }