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  }