10 "github.com/aws/aws-sdk-go/aws"
11 "github.com/aws/aws-sdk-go/aws/request"
14 const logReqMsg = `DEBUG: Request %s/%s Details:
15 ---[ REQUEST POST-SIGN ]-----------------------------
17 -----------------------------------------------------`
19 const logReqErrMsg = `DEBUG ERROR: Request %s/%s:
20 ---[ REQUEST DUMP ERROR ]-----------------------------
22 ------------------------------------------------------`
24 type logWriter struct {
25 // Logger is what we will use to log the payload of a response.
27 // buf stores the contents of what has been read
31 func (logger *logWriter) Write(b []byte) (int, error) {
32 return logger.buf.Write(b)
35 type teeReaderCloser struct {
36 // io.Reader will be a tee reader that is used during logging.
37 // This structure will read from a body and write the contents to a logger.
39 // Source is used just to close when we are done reading.
43 func (reader *teeReaderCloser) Close() error {
44 return reader.Source.Close()
47 // LogHTTPRequestHandler is a SDK request handler to log the HTTP request sent
48 // to a service. Will include the HTTP request body if the LogLevel of the
49 // request matches LogDebugWithHTTPBody.
50 var LogHTTPRequestHandler = request.NamedHandler{
51 Name: "awssdk.client.LogRequest",
55 func logRequest(r *request.Request) {
56 logBody := r.Config.LogLevel.Matches(aws.LogDebugWithHTTPBody)
57 bodySeekable := aws.IsReaderSeekable(r.Body)
59 b, err := httputil.DumpRequestOut(r.HTTPRequest, logBody)
61 r.Config.Logger.Log(fmt.Sprintf(logReqErrMsg,
62 r.ClientInfo.ServiceName, r.Operation.Name, err))
68 r.SetReaderBody(aws.ReadSeekCloser(r.HTTPRequest.Body))
70 // Reset the request body because dumpRequest will re-wrap the r.HTTPRequest's
71 // Body as a NoOpCloser and will not be reset after read by the HTTP
76 r.Config.Logger.Log(fmt.Sprintf(logReqMsg,
77 r.ClientInfo.ServiceName, r.Operation.Name, string(b)))
80 // LogHTTPRequestHeaderHandler is a SDK request handler to log the HTTP request sent
81 // to a service. Will only log the HTTP request's headers. The request payload
83 var LogHTTPRequestHeaderHandler = request.NamedHandler{
84 Name: "awssdk.client.LogRequestHeader",
88 func logRequestHeader(r *request.Request) {
89 b, err := httputil.DumpRequestOut(r.HTTPRequest, false)
91 r.Config.Logger.Log(fmt.Sprintf(logReqErrMsg,
92 r.ClientInfo.ServiceName, r.Operation.Name, err))
96 r.Config.Logger.Log(fmt.Sprintf(logReqMsg,
97 r.ClientInfo.ServiceName, r.Operation.Name, string(b)))
100 const logRespMsg = `DEBUG: Response %s/%s Details:
101 ---[ RESPONSE ]--------------------------------------
103 -----------------------------------------------------`
105 const logRespErrMsg = `DEBUG ERROR: Response %s/%s:
106 ---[ RESPONSE DUMP ERROR ]-----------------------------
108 -----------------------------------------------------`
110 // LogHTTPResponseHandler is a SDK request handler to log the HTTP response
111 // received from a service. Will include the HTTP response body if the LogLevel
112 // of the request matches LogDebugWithHTTPBody.
113 var LogHTTPResponseHandler = request.NamedHandler{
114 Name: "awssdk.client.LogResponse",
118 func logResponse(r *request.Request) {
119 lw := &logWriter{r.Config.Logger, bytes.NewBuffer(nil)}
121 logBody := r.Config.LogLevel.Matches(aws.LogDebugWithHTTPBody)
123 r.HTTPResponse.Body = &teeReaderCloser{
124 Reader: io.TeeReader(r.HTTPResponse.Body, lw),
125 Source: r.HTTPResponse.Body,
129 handlerFn := func(req *request.Request) {
130 b, err := httputil.DumpResponse(req.HTTPResponse, false)
132 lw.Logger.Log(fmt.Sprintf(logRespErrMsg,
133 req.ClientInfo.ServiceName, req.Operation.Name, err))
137 lw.Logger.Log(fmt.Sprintf(logRespMsg,
138 req.ClientInfo.ServiceName, req.Operation.Name, string(b)))
141 b, err := ioutil.ReadAll(lw.buf)
143 lw.Logger.Log(fmt.Sprintf(logRespErrMsg,
144 req.ClientInfo.ServiceName, req.Operation.Name, err))
148 lw.Logger.Log(string(b))
152 const handlerName = "awsdk.client.LogResponse.ResponseBody"
154 r.Handlers.Unmarshal.SetBackNamed(request.NamedHandler{
155 Name: handlerName, Fn: handlerFn,
157 r.Handlers.UnmarshalError.SetBackNamed(request.NamedHandler{
158 Name: handlerName, Fn: handlerFn,
162 // LogHTTPResponseHeaderHandler is a SDK request handler to log the HTTP
163 // response received from a service. Will only log the HTTP response's headers.
164 // The response payload will not be read.
165 var LogHTTPResponseHeaderHandler = request.NamedHandler{
166 Name: "awssdk.client.LogResponseHeader",
167 Fn: logResponseHeader,
170 func logResponseHeader(r *request.Request) {
171 if r.Config.Logger == nil {
175 b, err := httputil.DumpResponse(r.HTTPResponse, false)
177 r.Config.Logger.Log(fmt.Sprintf(logRespErrMsg,
178 r.ClientInfo.ServiceName, r.Operation.Name, err))
182 r.Config.Logger.Log(fmt.Sprintf(logRespMsg,
183 r.ClientInfo.ServiceName, r.Operation.Name, string(b)))