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