@@ -10,6 +10,7 @@ import (
1010"mime"
1111"net"
1212"net/http"
13+ "net/http/httputil"
1314"net/url"
1415"strings"
1516"sync"
@@ -90,6 +91,10 @@ type Client struct {
9091// LogBodies can be enabled to print request and response bodies to the logger.
9192LogBodies bool
9293
94+ // PlainLogger may be set to log HTTP traffic in a human-readable form.
95+ // It uses the LogBodies option.
96+ PlainLogger io.Writer
97+
9398// Trace can be enabled to propagate tracing spans to the Coder API.
9499// This is useful for tracking a request end-to-end.
95100Trace bool
@@ -109,6 +114,16 @@ func (c *Client) SetSessionToken(token string) {
109114c .sessionToken = token
110115}
111116
117+ func prefixLines (prefix ,s []byte ) []byte {
118+ ss := bytes .NewBuffer (make ([]byte ,0 ,len (s )* 2 ))
119+ for _ ,line := range bytes .Split (s , []byte ("\n " )) {
120+ _ ,_ = ss .Write (prefix )
121+ _ ,_ = ss .Write (line )
122+ _ = ss .WriteByte ('\n' )
123+ }
124+ return ss .Bytes ()
125+ }
126+
112127// Request performs a HTTP request with the body provided. The caller is
113128// responsible for closing the response body.
114129func (c * Client )Request (ctx context.Context ,method ,path string ,body interface {},opts ... RequestOption ) (* http.Response ,error ) {
@@ -155,6 +170,15 @@ func (c *Client) Request(ctx context.Context, method, path string, body interfac
155170return nil ,xerrors .Errorf ("create request: %w" ,err )
156171}
157172
173+ if c .PlainLogger != nil {
174+ out ,err := httputil .DumpRequest (req ,c .LogBodies )
175+ if err != nil {
176+ return nil ,xerrors .Errorf ("dump request: %w" ,err )
177+ }
178+ out = prefixLines ([]byte ("http --> " ),out )
179+ _ ,_ = c .PlainLogger .Write (out )
180+ }
181+
158182tokenHeader := c .SessionTokenHeader
159183if tokenHeader == "" {
160184tokenHeader = SessionTokenHeader
@@ -192,6 +216,15 @@ func (c *Client) Request(ctx context.Context, method, path string, body interfac
192216return nil ,err
193217}
194218
219+ if c .PlainLogger != nil {
220+ out ,err := httputil .DumpResponse (resp ,c .LogBodies )
221+ if err != nil {
222+ return nil ,xerrors .Errorf ("dump response: %w" ,err )
223+ }
224+ out = prefixLines ([]byte ("http <-- " ),out )
225+ _ ,_ = c .PlainLogger .Write (out )
226+ }
227+
195228span .SetAttributes (httpconv .ClientResponse (resp )... )
196229span .SetStatus (httpconv .ClientStatus (resp .StatusCode ))
197230