From c4af553eb50e655556248da18b18367d792a0042 Mon Sep 17 00:00:00 2001 From: Jorge Javier Araya Navarro Date: Fri, 27 Dec 2024 20:49:47 -0600 Subject: [PATCH] Implement debugging functionality when reading a response's body --- pkg/uhttp/body_print.go | 41 +++++++++++++++++++++++++++++++++++++++++ pkg/uhttp/wrapper.go | 13 +++++++++---- 2 files changed, 50 insertions(+), 4 deletions(-) create mode 100644 pkg/uhttp/body_print.go diff --git a/pkg/uhttp/body_print.go b/pkg/uhttp/body_print.go new file mode 100644 index 00000000..bf89c6c3 --- /dev/null +++ b/pkg/uhttp/body_print.go @@ -0,0 +1,41 @@ +package uhttp + +// Implements a debugging facility for request responses. This changes +// the behavior of `BaseHttpClient` with an unexported flag. +// +// If you always wanted to see the actual body of your response, now +// you can 👁️👄👁️undress it🫦 to uncover all its... data! + +import ( + "io" + "log" +) + +type printReader struct { + reader io.Reader +} + +func (pr *printReader) Read(p []byte) (int, error) { + n, err := pr.reader.Read(p) + if n > 0 { + log.Print(string(p[:n])) + } + + return n, err +} + +func wrapBodyToUndress(body io.Reader) io.Reader { + return &printReader{reader: body} +} + +type undressOption struct { + undress bool +} + +func (o undressOption) Apply(c *BaseHttpClient) { + c.debugPrintBody = o.undress +} + +func WithUndressBody(undress bool) WrapperOption { + return undressOption{undress: undress} +} diff --git a/pkg/uhttp/wrapper.go b/pkg/uhttp/wrapper.go index 5396e4f2..bef9493a 100644 --- a/pkg/uhttp/wrapper.go +++ b/pkg/uhttp/wrapper.go @@ -91,9 +91,10 @@ type ( NewRequest(ctx context.Context, method string, url *url.URL, options ...RequestOption) (*http.Request, error) } BaseHttpClient struct { - HttpClient *http.Client - rateLimiter uRateLimit.Limiter - baseHttpCache icache + HttpClient *http.Client + rateLimiter uRateLimit.Limiter + baseHttpCache icache + debugPrintBody bool } DoOption func(resp *WrapperResponse) error @@ -341,7 +342,11 @@ func (c *BaseHttpClient) Do(req *http.Request, options ...DoOption) (*http.Respo } // Replace resp.Body with a no-op closer so nobody has to worry about closing the reader. - resp.Body = io.NopCloser(bytes.NewBuffer(body)) + if c.debugPrintBody { + resp.Body = io.NopCloser(wrapBodyToUndress(bytes.NewBuffer(body))) + } else { + resp.Body = io.NopCloser(bytes.NewBuffer(body)) + } wresp := WrapperResponse{ Header: resp.Header,