Skip to content

Instantly share code, notes, and snippets.

@nielskrijger
Last active July 1, 2023 18:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nielskrijger/e680db57580d9939f2adf0fcd9eb35c6 to your computer and use it in GitHub Desktop.
Save nielskrijger/e680db57580d9939f2adf0fcd9eb35c6 to your computer and use it in GitHub Desktop.
httpmock LogResponder
func joinLines(lines []string, suffix, separator string) string {
var result string
for i, line := range lines {
result += fmt.Sprintf("%s%s", suffix, line)
if i < len(lines)-1 {
result += separator
}
}
return result
}
// formatRequest generates representation of the request
func formatRequest(req *http.Request) string {
var lines []string
lines = append(lines, fmt.Sprintf("%v %v %v", req.Method, req.URL, req.Proto))
lines = append(lines, fmt.Sprintf("Host: %v", req.Host))
// Loop through headers
for name, headers := range req.Header {
for _, h := range headers {
lines = append(lines, fmt.Sprintf("%v: %v", name, h))
}
}
result := joinLines(lines, "> ", "\n")
result += "\n\n"
// If this is a POST, add post data
if req.Method == "POST" {
req.ParseForm()
result += req.Form.Encode() + "\n\n"
}
return result
}
func formatResponse(res *http.Response) string {
var lines []string
lines = append(lines, fmt.Sprintf("%v %v %v", res.Proto, res.StatusCode, res.Status))
// Loop through headers
for name, headers := range res.Header {
for _, h := range headers {
lines = append(lines, fmt.Sprintf("%v: %v", name, h))
}
}
result := joinLines(lines, "< ", "\n")
result += "\n\n"
// If this response has a body add it
if res.Body != nil {
body, err := io.ReadAll(res.Body)
if err != nil {
result += fmt.Sprintf("reading request body: %v", err)
} else {
result += string(body)
res.Body = io.NopCloser(bytes.NewReader(body)) // Allow body to be read for a second time
}
result += "\n\n"
}
return result
}
// LogResponder logs the request and response for an outgoing request.
func LogResponder(req *http.Request) (*http.Response, error) {
httpmock.Deactivate()
defer httpmock.Activate()
res, err := http.DefaultClient.Do(req)
if err != nil {
return nil, err
}
defer res.Body.Close()
fmt.Print(formatRequest(req))
fmt.Print(formatResponse(res))
if res.Body != nil {
body, err := io.ReadAll(res.Body)
if err != nil {
return nil, err
}
res.Body = io.NopCloser(bytes.NewReader(body)) // Allow body to be read a second time by the app
}
return res, nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment