diff --git a/pkg/cmd/factory/http.go b/pkg/cmd/factory/http.go index 48f63e8ad..0c0abd7b2 100644 --- a/pkg/cmd/factory/http.go +++ b/pkg/cmd/factory/http.go @@ -9,6 +9,7 @@ import ( "github.com/cli/cli/api" "github.com/cli/cli/internal/ghinstance" + "github.com/cli/cli/internal/httpunix" "github.com/cli/cli/pkg/iostreams" ) @@ -59,6 +60,29 @@ type configGetter interface { // generic authenticated HTTP client for commands func NewHTTPClient(io *iostreams.IOStreams, cfg configGetter, appVersion string, setAccept bool) (*http.Client, error) { var opts []api.ClientOption + + // We need to check and potentially add the unix socket roundtripper option + // before adding any other options, since if we are going to use the unix + // socket transport, it needs to form the base of the transport chain + // represented by invocations of opts... + // + // Another approach might be to change the signature of api.NewHTTPClient to + // take an explicit base http.RoundTripper as its first parameter (it + // currently defaults internally to http.DefaultTransport), or add another + // variant like api.NewHTTPClientWithBaseRoundTripper. But, the only caller + // which would use that non-default behavior is right here, and it doesn't + // seem worth the cognitive overhead everywhere else just to serve this one + // use case. + unixSocket, err := cfg.Get("", "http_unix_socket") + if err != nil { + return nil, err + } + if unixSocket != "" { + opts = append(opts, api.ClientOption(func(http.RoundTripper) http.RoundTripper { + return httpunix.NewRoundTripper(unixSocket) + })) + } + if verbose := os.Getenv("DEBUG"); verbose != "" { logTraffic := strings.Contains(verbose, "api") opts = append(opts, api.VerboseLog(io.ErrOut, logTraffic, io.IsStderrTTY()))