diff --git a/cmd/camget/camget.go b/cmd/camget/camget.go index 5f782ab57..7ee0df9c1 100644 --- a/cmd/camget/camget.go +++ b/cmd/camget/camget.go @@ -23,7 +23,6 @@ import ( "fmt" "io" "log" - "net" "net/http" "os" "path/filepath" @@ -89,18 +88,11 @@ func main() { } } - httpStats := &httputil.StatsTransport{ - VerboseLog: *flagHTTP, - } - if *flagHTTP { - httpStats.Transport = &http.Transport{ - Dial: func(net_, addr string) (net.Conn, error) { - log.Printf("Dialing %s", addr) - return net.Dial(net_, addr) - }, - } - } - cl.SetHTTPClient(&http.Client{Transport: httpStats}) + tr := cl.TransportForConfig(&client.TransportConfig{ + Verbose: *flagHTTP, + }) + httpStats, _ := tr.(*httputil.StatsTransport) + cl.SetHTTPClient(&http.Client{Transport: tr}) diskCacheFetcher, err := cacher.NewDiskCache(cl) if err != nil { diff --git a/cmd/cammount/cammount.go b/cmd/cammount/cammount.go index 04e3cfa1e..b08430b89 100644 --- a/cmd/cammount/cammount.go +++ b/cmd/cammount/cammount.go @@ -85,6 +85,7 @@ func main() { } else { cl = client.NewOrFail() // automatic from flags } + // TODO(mpl): probably needs the transport setup for trusted certs here. diskCacheFetcher, err := cacher.NewDiskCache(cl) if err != nil { diff --git a/cmd/camput/camput.go b/cmd/camput/camput.go index 345e0324b..3dc190760 100644 --- a/cmd/camput/camput.go +++ b/cmd/camput/camput.go @@ -107,31 +107,17 @@ func newUploader() *Uploader { cc.SetLogger(nil) } - var transport http.RoundTripper proxy := http.ProxyFromEnvironment if flagProxyLocal { proxy = proxyFromEnvironment } - tlsConfig, err := cc.TLSConfig() - if err != nil { - log.Fatalf("Error while configuring TLS for client: %v", err) - } - transport = &http.Transport{ - Dial: cc.DialFunc(), - TLSClientConfig: tlsConfig, - Proxy: proxy, - } - - httpStats := &httputil.StatsTransport{ - VerboseLog: *flagHTTP, - Transport: transport, - } - transport = httpStats - - if client.AndroidOutput() { - transport = client.AndroidStatsTransport{transport} - } - cc.SetHTTPClient(&http.Client{Transport: transport}) + tr := cc.TransportForConfig( + &client.TransportConfig{ + Proxy: proxy, + Verbose: *flagHTTP, + }) + httpStats, _ := tr.(*httputil.StatsTransport) + cc.SetHTTPClient(&http.Client{Transport: tr}) pwd, err := os.Getwd() if err != nil { diff --git a/cmd/camtool/sync.go b/cmd/camtool/sync.go index b79b10bc4..93a8cce12 100644 --- a/cmd/camtool/sync.go +++ b/cmd/camtool/sync.go @@ -160,6 +160,7 @@ func (c *syncCmd) storageFromParam(which storageType, val string) (blobserver.St return disk, nil } cl := client.New(val) + // TODO(mpl): probably needs the transport setup for trusted certs here. cl.SetupAuth() cl.SetLogger(c.logger) return noHub{cl}, nil diff --git a/pkg/client/client.go b/pkg/client/client.go index ff0069e23..c5e525698 100644 --- a/pkg/client/client.go +++ b/pkg/client/client.go @@ -35,6 +35,7 @@ import ( "camlistore.org/pkg/auth" "camlistore.org/pkg/blobref" + "camlistore.org/pkg/httputil" "camlistore.org/pkg/misc" "camlistore.org/pkg/schema" "camlistore.org/pkg/search" @@ -120,6 +121,49 @@ func NewOrFail() *Client { return c } +// TransportConfig contains options for SetupTransport. +type TransportConfig struct { + // Proxy optionally specifies the Proxy for the transport. Useful with + // camput for debugging even localhost requests. + Proxy func(*http.Request) (*url.URL, error) + Verbose bool // Verbose enables verbose logging of HTTP requests. +} + +// TransportForConfig returns a transport for the client, setting the correct +// Proxy, Dial, and TLSClientConfig if needed. It does not mutate c. +// It is the caller's responsibility to then use that transport to set +// the client's httpClient with SetHTTPClient. +func (c *Client) TransportForConfig(tc *TransportConfig) http.RoundTripper { + if c == nil { + return nil + } + tlsConfig, err := c.TLSConfig() + if err != nil { + log.Fatalf("Error while configuring TLS for client: %v", err) + } + var transport http.RoundTripper + proxy := http.ProxyFromEnvironment + if tc != nil && tc.Proxy != nil { + proxy = tc.Proxy + } + transport = &http.Transport{ + Dial: c.DialFunc(), + TLSClientConfig: tlsConfig, + Proxy: proxy, + } + httpStats := &httputil.StatsTransport{ + Transport: transport, + } + if tc != nil { + httpStats.VerboseLog = tc.Verbose + } + transport = httpStats + if AndroidOutput() { + transport = &AndroidStatsTransport{transport} + } + return transport +} + var shareURLRx = regexp.MustCompile(`^(.+)/(` + blobref.Pattern + ")$") func NewFromShareRoot(shareBlobURL string) (c *Client, target *blobref.BlobRef, err error) { @@ -139,7 +183,10 @@ func NewFromShareRoot(shareBlobURL string) (c *Client, target *blobref.BlobRef, c.via = make(map[string]string) root = m[2] - res, err := http.Get(shareBlobURL) + c.SetHTTPClient(&http.Client{Transport: c.TransportForConfig(nil)}) + + req := c.newRequest("GET", shareBlobURL, nil) + res, err := c.doReqGated(req) if err != nil { return nil, nil, fmt.Errorf("Error fetching %s: %v", shareBlobURL, err) }