isle/go/toolkit/http.go

100 lines
2.2 KiB
Go
Raw Permalink Normal View History

2024-11-19 13:12:17 +00:00
package toolkit
import (
"net/http"
"net/http/httputil"
"net/url"
"dev.mediocregopher.com/mediocre-go-lib.git/mlog"
"github.com/tv42/httpunix"
)
// HTTPClient is an interface around the default http.Client type.
type HTTPClient interface {
Do(*http.Request) (*http.Response, error)
// Close cleans up any resources being held by the HTTPClient.
Close() error
}
type httpClient struct {
logger *mlog.Logger
*http.Client
}
// NewHTTPClient returns a new HTTPClient using a clone of
// [http.DefaultTransport].
func NewHTTPClient(logger *mlog.Logger) HTTPClient {
return &httpClient{
logger,
&http.Client{
Transport: http.DefaultTransport.(*http.Transport).Clone(),
},
}
}
// NewUnixHTTPClient returns an HTTPClient which will use the given
// unixSocketPath to serve requests. The base URL (scheme and host) which should
// be used for requests is returned as well.
func NewUnixHTTPClient(
logger *mlog.Logger, unixSocketPath string,
) (
HTTPClient, *url.URL,
) {
const host = "uds"
u := &url.URL{
Scheme: httpunix.Scheme,
Host: host,
}
transport := new(httpunix.Transport)
transport.RegisterLocation(host, unixSocketPath)
return &httpClient{logger, &http.Client{Transport: transport}}, u
}
func (c *httpClient) Do(req *http.Request) (*http.Response, error) {
if c.logger.MaxLevel() < mlog.LevelDebug.Int() {
return c.Client.Do(req)
}
var (
ctx = req.Context()
origScheme = req.URL.Scheme
)
// httputil.DumpRequestOut doesn't like the httpunix.Scheme, so we
// temporarily switch it.
if req.URL.Scheme == httpunix.Scheme {
req.URL.Scheme = "http"
}
reqB, err := httputil.DumpRequestOut(req, true)
if err != nil {
c.logger.Error(ctx, "failed to dump http request", err)
} else {
c.logger.Debug(ctx, "------ request ------\n"+string(reqB)+"\n")
}
req.URL.Scheme = origScheme
res, err := c.Client.Do(req)
if res != nil {
resB, err := httputil.DumpResponse(res, true)
if err != nil {
c.logger.Error(ctx, "failed to dump http response", err)
} else {
c.logger.Debug(ctx, "------ response ------\n"+string(resB)+"\n")
}
}
return res, err
}
func (c *httpClient) Close() error {
c.CloseIdleConnections()
return nil
}