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  }