74 lines
2.6 KiB
Go
74 lines
2.6 KiB
Go
package pipeline
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"net/http"
|
|
"sort"
|
|
"strings"
|
|
)
|
|
|
|
// The Response interface exposes an http.Response object as it returns through the pipeline of Policy objects.
|
|
// This ensures that Policy objects have access to the HTTP response. However, the object this interface encapsulates
|
|
// might be a struct with additional fields that is created by a Policy object (typically a method-specific Factory).
|
|
// The method that injected the method-specific Factory gets this returned Response and performs a type assertion
|
|
// to the expected struct and returns the struct to its caller.
|
|
type Response interface {
|
|
Response() *http.Response
|
|
}
|
|
|
|
// This is the default struct that has the http.Response.
|
|
// A method can replace this struct with its own struct containing an http.Response
|
|
// field and any other additional fields.
|
|
type httpResponse struct {
|
|
response *http.Response
|
|
}
|
|
|
|
// NewHTTPResponse is typically called by a Policy object to return a Response object.
|
|
func NewHTTPResponse(response *http.Response) Response {
|
|
return &httpResponse{response: response}
|
|
}
|
|
|
|
// This method satisfies the public Response interface's Response method
|
|
func (r httpResponse) Response() *http.Response {
|
|
return r.response
|
|
}
|
|
|
|
// WriteRequestWithResponse appends a formatted HTTP request into a Buffer. If request and/or err are
|
|
// not nil, then these are also written into the Buffer.
|
|
func WriteRequestWithResponse(b *bytes.Buffer, request *http.Request, response *http.Response, err error) {
|
|
// Write the request into the buffer.
|
|
fmt.Fprint(b, " "+request.Method+" "+request.URL.String()+"\n")
|
|
writeHeader(b, request.Header)
|
|
if response != nil {
|
|
fmt.Fprintln(b, " --------------------------------------------------------------------------------")
|
|
fmt.Fprint(b, " RESPONSE Status: "+response.Status+"\n")
|
|
writeHeader(b, response.Header)
|
|
}
|
|
if err != nil {
|
|
fmt.Fprintln(b, " --------------------------------------------------------------------------------")
|
|
fmt.Fprint(b, " ERROR:\n"+err.Error()+"\n")
|
|
}
|
|
}
|
|
|
|
// formatHeaders appends an HTTP request's or response's header into a Buffer.
|
|
func writeHeader(b *bytes.Buffer, header map[string][]string) {
|
|
if len(header) == 0 {
|
|
b.WriteString(" (no headers)\n")
|
|
return
|
|
}
|
|
keys := make([]string, 0, len(header))
|
|
// Alphabetize the headers
|
|
for k := range header {
|
|
keys = append(keys, k)
|
|
}
|
|
sort.Strings(keys)
|
|
for _, k := range keys {
|
|
// Redact the value of any Authorization header to prevent security information from persisting in logs
|
|
value := interface{}("REDACTED")
|
|
if !strings.EqualFold(k, "Authorization") {
|
|
value = header[k]
|
|
}
|
|
fmt.Fprintf(b, " %s: %+v\n", k, value)
|
|
}
|
|
}
|