github.com/akamai/AkamaiOPEN-edgegrid-golang/v2@v2.17.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/v2/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 // 99 func Must(sess Session, err error) Session { 100 if err != nil { 101 panic(err) 102 } 103 104 return sess 105 } 106 107 // WithClient creates a client using the specified http.Client 108 func WithClient(client *http.Client) Option { 109 return func(s *session) { 110 s.client = client 111 } 112 } 113 114 // WithLog sets the log interface for the client 115 func WithLog(l log.Interface) Option { 116 return func(s *session) { 117 s.log = l 118 } 119 } 120 121 // WithUserAgent sets the user agent string for the client 122 func WithUserAgent(u string) Option { 123 return func(s *session) { 124 s.userAgent = u 125 } 126 } 127 128 // WithSigner sets the request signer for the session 129 func WithSigner(signer edgegrid.Signer) Option { 130 return func(s *session) { 131 s.signer = signer 132 } 133 } 134 135 // WithHTTPTracing sets the request and response dump for debugging 136 func WithHTTPTracing(trace bool) Option { 137 return func(s *session) { 138 s.trace = trace 139 } 140 } 141 142 // Log will return the context logger, or the session log 143 func (s *session) Log(ctx context.Context) log.Interface { 144 if o := ctx.Value(contextOptionKey); o != nil { 145 if ops, ok := o.(*contextOptions); ok && ops.log != nil { 146 return ops.log 147 } 148 } 149 if s.log != nil { 150 return s.log 151 } 152 153 return &log.Logger{ 154 Handler: discard.New(), 155 } 156 } 157 158 // Client returns the http client interface 159 func (s *session) Client() *http.Client { 160 return s.client 161 } 162 163 // ContextWithOptions adds request specific options to the context 164 // This log will debug the request only using the provided log 165 func ContextWithOptions(ctx context.Context, opts ...ContextOption) context.Context { 166 o := new(contextOptions) 167 for _, opt := range opts { 168 opt(o) 169 } 170 171 return context.WithValue(ctx, contextOptionKey, o) 172 } 173 174 // WithContextLog provides a context specific logger 175 func WithContextLog(l log.Interface) ContextOption { 176 return func(o *contextOptions) { 177 o.log = l 178 } 179 } 180 181 // WithContextHeaders sets the context headers 182 func WithContextHeaders(h http.Header) ContextOption { 183 return func(o *contextOptions) { 184 o.header = h 185 } 186 }