7 "github.com/aws/aws-sdk-go/aws"
8 "github.com/aws/aws-sdk-go/aws/awserr"
9 "github.com/aws/aws-sdk-go/aws/client/metadata"
10 "github.com/aws/aws-sdk-go/aws/request"
13 // A Config provides configuration to a service client instance.
16 Handlers request.Handlers
22 // ConfigProvider provides a generic way for a service client to receive
23 // the ClientConfig without circular dependencies.
24 type ConfigProvider interface {
25 ClientConfig(serviceName string, cfgs ...*aws.Config) Config
28 // ConfigNoResolveEndpointProvider same as ConfigProvider except it will not
29 // resolve the endpoint automatically. The service client's endpoint must be
30 // provided via the aws.Config.Endpoint field.
31 type ConfigNoResolveEndpointProvider interface {
32 ClientConfigNoResolveEndpoint(cfgs ...*aws.Config) Config
35 // A Client implements the base client request and response handling
36 // used by all service clients.
42 Handlers request.Handlers
45 // New will return a pointer to a new initialized service client.
46 func New(cfg aws.Config, info metadata.ClientInfo, handlers request.Handlers, options ...func(*Client)) *Client {
50 Handlers: handlers.Copy(),
53 switch retryer, ok := cfg.Retryer.(request.Retryer); {
56 case cfg.Retryer != nil && cfg.Logger != nil:
57 s := fmt.Sprintf("WARNING: %T does not implement request.Retryer; using DefaultRetryer instead", cfg.Retryer)
61 maxRetries := aws.IntValue(cfg.MaxRetries)
62 if cfg.MaxRetries == nil || maxRetries == aws.UseServiceDefaultRetries {
65 svc.Retryer = DefaultRetryer{NumMaxRetries: maxRetries}
68 svc.AddDebugHandlers()
70 for _, option := range options {
77 // NewRequest returns a new Request pointer for the service API
78 // operation and parameters.
79 func (c *Client) NewRequest(operation *request.Operation, params interface{}, data interface{}) *request.Request {
80 return request.New(c.Config, c.ClientInfo, c.Handlers, c.Retryer, operation, params, data)
83 // AddDebugHandlers injects debug logging handlers into the service to log request
85 func (c *Client) AddDebugHandlers() {
86 if !c.Config.LogLevel.AtLeast(aws.LogDebug) {
90 c.Handlers.Send.PushFrontNamed(request.NamedHandler{Name: "awssdk.client.LogRequest", Fn: logRequest})
91 c.Handlers.Send.PushBackNamed(request.NamedHandler{Name: "awssdk.client.LogResponse", Fn: logResponse})
94 const logReqMsg = `DEBUG: Request %s/%s Details:
95 ---[ REQUEST POST-SIGN ]-----------------------------
97 -----------------------------------------------------`
99 const logReqErrMsg = `DEBUG ERROR: Request %s/%s:
100 ---[ REQUEST DUMP ERROR ]-----------------------------
102 -----------------------------------------------------`
104 func logRequest(r *request.Request) {
105 logBody := r.Config.LogLevel.Matches(aws.LogDebugWithHTTPBody)
106 dumpedBody, err := httputil.DumpRequestOut(r.HTTPRequest, logBody)
108 r.Config.Logger.Log(fmt.Sprintf(logReqErrMsg, r.ClientInfo.ServiceName, r.Operation.Name, err))
109 r.Error = awserr.New(request.ErrCodeRead, "an error occurred during request body reading", err)
114 // Reset the request body because dumpRequest will re-wrap the r.HTTPRequest's
115 // Body as a NoOpCloser and will not be reset after read by the HTTP
120 r.Config.Logger.Log(fmt.Sprintf(logReqMsg, r.ClientInfo.ServiceName, r.Operation.Name, string(dumpedBody)))
123 const logRespMsg = `DEBUG: Response %s/%s Details:
124 ---[ RESPONSE ]--------------------------------------
126 -----------------------------------------------------`
128 const logRespErrMsg = `DEBUG ERROR: Response %s/%s:
129 ---[ RESPONSE DUMP ERROR ]-----------------------------
131 -----------------------------------------------------`
133 func logResponse(r *request.Request) {
134 var msg = "no response data"
135 if r.HTTPResponse != nil {
136 logBody := r.Config.LogLevel.Matches(aws.LogDebugWithHTTPBody)
137 dumpedBody, err := httputil.DumpResponse(r.HTTPResponse, logBody)
139 r.Config.Logger.Log(fmt.Sprintf(logRespErrMsg, r.ClientInfo.ServiceName, r.Operation.Name, err))
140 r.Error = awserr.New(request.ErrCodeRead, "an error occurred during response body reading", err)
144 msg = string(dumpedBody)
145 } else if r.Error != nil {
146 msg = r.Error.Error()
148 r.Config.Logger.Log(fmt.Sprintf(logRespMsg, r.ClientInfo.ServiceName, r.Operation.Name, msg))