1package client
2
3import (
4	"fmt"
5
6	"github.com/aws/aws-sdk-go/aws"
7	"github.com/aws/aws-sdk-go/aws/client/metadata"
8	"github.com/aws/aws-sdk-go/aws/request"
9)
10
11// A Config provides configuration to a service client instance.
12type Config struct {
13	Config        *aws.Config
14	Handlers      request.Handlers
15	Endpoint      string
16	SigningRegion string
17	SigningName   string
18
19	// States that the signing name did not come from a modeled source but
20	// was derived based on other data. Used by service client constructors
21	// to determine if the signin name can be overriden based on metadata the
22	// service has.
23	SigningNameDerived bool
24}
25
26// ConfigProvider provides a generic way for a service client to receive
27// the ClientConfig without circular dependencies.
28type ConfigProvider interface {
29	ClientConfig(serviceName string, cfgs ...*aws.Config) Config
30}
31
32// ConfigNoResolveEndpointProvider same as ConfigProvider except it will not
33// resolve the endpoint automatically. The service client's endpoint must be
34// provided via the aws.Config.Endpoint field.
35type ConfigNoResolveEndpointProvider interface {
36	ClientConfigNoResolveEndpoint(cfgs ...*aws.Config) Config
37}
38
39// A Client implements the base client request and response handling
40// used by all service clients.
41type Client struct {
42	request.Retryer
43	metadata.ClientInfo
44
45	Config   aws.Config
46	Handlers request.Handlers
47}
48
49// New will return a pointer to a new initialized service client.
50func New(cfg aws.Config, info metadata.ClientInfo, handlers request.Handlers, options ...func(*Client)) *Client {
51	svc := &Client{
52		Config:     cfg,
53		ClientInfo: info,
54		Handlers:   handlers.Copy(),
55	}
56
57	switch retryer, ok := cfg.Retryer.(request.Retryer); {
58	case ok:
59		svc.Retryer = retryer
60	case cfg.Retryer != nil && cfg.Logger != nil:
61		s := fmt.Sprintf("WARNING: %T does not implement request.Retryer; using DefaultRetryer instead", cfg.Retryer)
62		cfg.Logger.Log(s)
63		fallthrough
64	default:
65		maxRetries := aws.IntValue(cfg.MaxRetries)
66		if cfg.MaxRetries == nil || maxRetries == aws.UseServiceDefaultRetries {
67			maxRetries = 3
68		}
69		svc.Retryer = DefaultRetryer{NumMaxRetries: maxRetries}
70	}
71
72	svc.AddDebugHandlers()
73
74	for _, option := range options {
75		option(svc)
76	}
77
78	return svc
79}
80
81// NewRequest returns a new Request pointer for the service API
82// operation and parameters.
83func (c *Client) NewRequest(operation *request.Operation, params interface{}, data interface{}) *request.Request {
84	return request.New(c.Config, c.ClientInfo, c.Handlers, c.Retryer, operation, params, data)
85}
86
87// AddDebugHandlers injects debug logging handlers into the service to log request
88// debug information.
89func (c *Client) AddDebugHandlers() {
90	if !c.Config.LogLevel.AtLeast(aws.LogDebug) {
91		return
92	}
93
94	c.Handlers.Send.PushFrontNamed(LogHTTPRequestHandler)
95	c.Handlers.Send.PushBackNamed(LogHTTPResponseHandler)
96}
97