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 func logRequest(r *request.Request) {
48 logBody := r.Config.LogLevel.Matches(aws.LogDebugWithHTTPBody)
49 dumpedBody, err := httputil.DumpRequestOut(r.HTTPRequest, logBody)
51 r.Config.Logger.Log(fmt.Sprintf(logReqErrMsg, r.ClientInfo.ServiceName, r.Operation.Name, err))
56 // Reset the request body because dumpRequest will re-wrap the r.HTTPRequest's
57 // Body as a NoOpCloser and will not be reset after read by the HTTP
62 r.Config.Logger.Log(fmt.Sprintf(logReqMsg, r.ClientInfo.ServiceName, r.Operation.Name, string(dumpedBody)))
65 const logRespMsg = `DEBUG: Response %s/%s Details:
66 ---[ RESPONSE ]--------------------------------------
68 -----------------------------------------------------`
70 const logRespErrMsg = `DEBUG ERROR: Response %s/%s:
71 ---[ RESPONSE DUMP ERROR ]-----------------------------
73 -----------------------------------------------------`
75 func logResponse(r *request.Request) {
76 lw := &logWriter{r.Config.Logger, bytes.NewBuffer(nil)}
77 r.HTTPResponse.Body = &teeReaderCloser{
78 Reader: io.TeeReader(r.HTTPResponse.Body, lw),
79 Source: r.HTTPResponse.Body,
82 handlerFn := func(req *request.Request) {
83 body, err := httputil.DumpResponse(req.HTTPResponse, false)
85 lw.Logger.Log(fmt.Sprintf(logRespErrMsg, req.ClientInfo.ServiceName, req.Operation.Name, err))
89 b, err := ioutil.ReadAll(lw.buf)
91 lw.Logger.Log(fmt.Sprintf(logRespErrMsg, req.ClientInfo.ServiceName, req.Operation.Name, err))
94 lw.Logger.Log(fmt.Sprintf(logRespMsg, req.ClientInfo.ServiceName, req.Operation.Name, string(body)))
95 if req.Config.LogLevel.Matches(aws.LogDebugWithHTTPBody) {
96 lw.Logger.Log(string(b))
100 const handlerName = "awsdk.client.LogResponse.ResponseBody"
102 r.Handlers.Unmarshal.SetBackNamed(request.NamedHandler{
103 Name: handlerName, Fn: handlerFn,
105 r.Handlers.UnmarshalError.SetBackNamed(request.NamedHandler{
106 Name: handlerName, Fn: handlerFn,