github.com/jghiloni/cli@v6.28.1-0.20170628223758-0ce05fe032a2+incompatible/api/cloudcontroller/wrapper/request_logger.go (about)

     1  package wrapper
     2  
     3  import (
     4  	"io/ioutil"
     5  	"net/http"
     6  	"sort"
     7  	"strings"
     8  	"time"
     9  
    10  	"code.cloudfoundry.org/cli/api/cloudcontroller"
    11  )
    12  
    13  //go:generate counterfeiter . RequestLoggerOutput
    14  
    15  // RequestLoggerOutput is the interface for displaying logs
    16  type RequestLoggerOutput interface {
    17  	DisplayJSONBody(body []byte) error
    18  	DisplayHeader(name string, value string) error
    19  	DisplayHost(name string) error
    20  	DisplayRequestHeader(method string, uri string, httpProtocol string) error
    21  	DisplayResponseHeader(httpProtocol string, status string) error
    22  	DisplayType(name string, requestDate time.Time) error
    23  	HandleInternalError(err error)
    24  	Start() error
    25  	Stop() error
    26  }
    27  
    28  // RequestLogger is the wrapper that logs requests to and responses from the
    29  // Cloud Controller server
    30  type RequestLogger struct {
    31  	connection cloudcontroller.Connection
    32  	output     RequestLoggerOutput
    33  }
    34  
    35  // NewRequestLogger returns a pointer to a RequestLogger wrapper
    36  func NewRequestLogger(output RequestLoggerOutput) *RequestLogger {
    37  	return &RequestLogger{
    38  		output: output,
    39  	}
    40  }
    41  
    42  // Wrap sets the connection on the RequestLogger and returns itself
    43  func (logger *RequestLogger) Wrap(innerconnection cloudcontroller.Connection) cloudcontroller.Connection {
    44  	logger.connection = innerconnection
    45  	return logger
    46  }
    47  
    48  // Make records the request and the response to UI
    49  func (logger *RequestLogger) Make(request *cloudcontroller.Request, passedResponse *cloudcontroller.Response) error {
    50  	err := logger.displayRequest(request)
    51  	if err != nil {
    52  		logger.output.HandleInternalError(err)
    53  	}
    54  
    55  	err = logger.connection.Make(request, passedResponse)
    56  
    57  	if passedResponse.HTTPResponse != nil {
    58  		displayErr := logger.displayResponse(passedResponse)
    59  		if displayErr != nil {
    60  			logger.output.HandleInternalError(displayErr)
    61  		}
    62  	}
    63  
    64  	return err
    65  }
    66  
    67  func (logger *RequestLogger) displayRequest(request *cloudcontroller.Request) error {
    68  	err := logger.output.Start()
    69  	if err != nil {
    70  		return err
    71  	}
    72  	defer logger.output.Stop()
    73  
    74  	err = logger.output.DisplayType("REQUEST", time.Now())
    75  	if err != nil {
    76  		return err
    77  	}
    78  	err = logger.output.DisplayRequestHeader(request.Method, request.URL.RequestURI(), request.Proto)
    79  	if err != nil {
    80  		return err
    81  	}
    82  	err = logger.output.DisplayHost(request.URL.Host)
    83  	if err != nil {
    84  		return err
    85  	}
    86  	err = logger.displaySortedHeaders(request.Header)
    87  	if err != nil {
    88  		return err
    89  	}
    90  
    91  	if request.Body != nil && strings.Contains(request.Header.Get("Content-Type"), "json") {
    92  		rawRequestBody, err := ioutil.ReadAll(request.Body)
    93  		if err != nil {
    94  			return err
    95  		}
    96  
    97  		defer request.ResetBody()
    98  
    99  		err = logger.output.DisplayJSONBody(rawRequestBody)
   100  		if err != nil {
   101  			return err
   102  		}
   103  	}
   104  
   105  	return nil
   106  }
   107  
   108  func (logger *RequestLogger) displayResponse(passedResponse *cloudcontroller.Response) error {
   109  	err := logger.output.Start()
   110  	if err != nil {
   111  		return err
   112  	}
   113  	defer logger.output.Stop()
   114  
   115  	err = logger.output.DisplayType("RESPONSE", time.Now())
   116  	if err != nil {
   117  		return err
   118  	}
   119  	err = logger.output.DisplayResponseHeader(passedResponse.HTTPResponse.Proto, passedResponse.HTTPResponse.Status)
   120  	if err != nil {
   121  		return err
   122  	}
   123  	err = logger.displaySortedHeaders(passedResponse.HTTPResponse.Header)
   124  	if err != nil {
   125  		return err
   126  	}
   127  	return logger.output.DisplayJSONBody(passedResponse.RawResponse)
   128  }
   129  
   130  func (logger *RequestLogger) displaySortedHeaders(headers http.Header) error {
   131  	keys := []string{}
   132  	for key, _ := range headers {
   133  		keys = append(keys, key)
   134  	}
   135  	sort.Strings(keys)
   136  
   137  	for _, key := range keys {
   138  		for _, value := range headers[key] {
   139  			err := logger.output.DisplayHeader(key, redactHeaders(key, value))
   140  			if err != nil {
   141  				return err
   142  			}
   143  		}
   144  	}
   145  	return nil
   146  }
   147  
   148  func redactHeaders(key string, value string) string {
   149  	if key == "Authorization" {
   150  		return "[PRIVATE DATA HIDDEN]"
   151  	}
   152  	return value
   153  }