github.com/akamai/AkamaiOPEN-edgegrid-golang/v8@v8.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/v8/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 requestLimit int 44 } 45 46 contextOptions struct { 47 log log.Interface 48 header http.Header 49 } 50 51 // Option defines a client option 52 Option func(*session) 53 54 contextKey string 55 56 // ContextOption are options on the context 57 ContextOption func(*contextOptions) 58 ) 59 60 var ( 61 contextOptionKey = contextKey("sessionContext") 62 ) 63 64 const ( 65 // Version is the client version 66 Version = "8.0.0" 67 ) 68 69 // New returns a new session 70 func New(opts ...Option) (Session, error) { 71 var ( 72 defaultUserAgent = "Akamai-Open-Edgegrid-golang/" + Version + " golang/" + strings.TrimPrefix(runtime.Version(), "go") 73 ) 74 75 s := &session{ 76 client: http.DefaultClient, 77 log: log.Log, 78 userAgent: defaultUserAgent, 79 trace: false, 80 } 81 82 for _, opt := range opts { 83 opt(s) 84 } 85 86 if s.signer == nil { 87 config, err := edgegrid.New() 88 if err != nil { 89 return nil, err 90 } 91 s.signer = config 92 } 93 94 return s, nil 95 } 96 97 // Must is a helper tthat will result in a panic if an error is returned 98 // ex. sess := Must(New()) 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 // WithRequestLimit sets the maximum number of API calls that the provider will make per second. 136 func WithRequestLimit(requestLimit int) Option { 137 return func(s *session) { 138 s.requestLimit = requestLimit 139 } 140 } 141 142 // WithHTTPTracing sets the request and response dump for debugging 143 func WithHTTPTracing(trace bool) Option { 144 return func(s *session) { 145 s.trace = trace 146 } 147 } 148 149 // Log will return the context logger, or the session log 150 func (s *session) Log(ctx context.Context) log.Interface { 151 if o := ctx.Value(contextOptionKey); o != nil { 152 if ops, ok := o.(*contextOptions); ok && ops.log != nil { 153 return ops.log 154 } 155 } 156 if s.log != nil { 157 return s.log 158 } 159 160 return &log.Logger{ 161 Handler: discard.New(), 162 } 163 } 164 165 // Client returns the http client interface 166 func (s *session) Client() *http.Client { 167 return s.client 168 } 169 170 // ContextWithOptions adds request specific options to the context 171 // This log will debug the request only using the provided log 172 func ContextWithOptions(ctx context.Context, opts ...ContextOption) context.Context { 173 o := new(contextOptions) 174 for _, opt := range opts { 175 opt(o) 176 } 177 178 return context.WithValue(ctx, contextOptionKey, o) 179 } 180 181 // WithContextLog provides a context specific logger 182 func WithContextLog(l log.Interface) ContextOption { 183 return func(o *contextOptions) { 184 o.log = l 185 } 186 } 187 188 // WithContextHeaders sets the context headers 189 func WithContextHeaders(h http.Header) ContextOption { 190 return func(o *contextOptions) { 191 o.header = h 192 } 193 }