diff --git a/cmd/depsyncer/main.go b/cmd/depsyncer/main.go index 9e6642e..b1ae9ff 100644 --- a/cmd/depsyncer/main.go +++ b/cmd/depsyncer/main.go @@ -5,7 +5,6 @@ import ( "flag" "fmt" stdlog "log" - "net/http" "os" "os/signal" "sync" @@ -34,6 +33,7 @@ func main() { flStorage = flag.String("storage", "file", "storage backend") flDSN = flag.String("storage-dsn", "", "storage data source name") flWebhook = flag.String("webhook-url", "", "URL to send requests to") + flUA = flag.String("user-agent", godep.UserAgent, "User-Agent string to use") ) flag.Usage = func() { fmt.Fprintf(flag.CommandLine.Output(), "Usage: %s [flags] [DEPname2 [...]]\nFlags:\n", os.Args[0]) @@ -118,7 +118,7 @@ func main() { } }() - client := godep.NewClient(storage, http.DefaultClient) + client := godep.NewClient(storage, godep.WithUserAgent(*flUA)) var wg sync.WaitGroup diff --git a/godep/client.go b/godep/client.go index 92e0903..8945312 100644 --- a/godep/client.go +++ b/godep/client.go @@ -15,7 +15,7 @@ import ( const ( mediaType = "application/json;charset=UTF8" - userAgent = "nanodep-godep/0" + UserAgent = "nanodep-g-o-dep/0" ) // HTTPError encapsulates an HTTP response error from the DEP requests. @@ -65,27 +65,45 @@ type ClientStorage interface { // Client represents an Apple DEP API client identified by a single DEP name. type Client struct { - store ClientStorage + store ClientStorage + client *http.Client // for DEP API authentication and session management + ua string // HTTP User-Agent +} + +// Options change the configuration of the godep Client. +type Option func(*Client) - // an HTTP client that handles DEP API authentication and session management - client *http.Client +// WithUserAgent sets the the HTTP User-Agent string to be used on each request. +func WithUserAgent(ua string) Option { + return func(c *Client) { + c.ua = ua + } } -// NewClient creates new Client and reads authentication and config data -// from store. The provided client is copied and modified by wrapping its +// WithClient configures the HTTP client to be used. +// The provided client is copied and modified by wrapping its // transport in a new NanoDEP transport (which transparently handles -// authentication and session management). If client is nil then +// authentication and session management). If not set then // http.DefaultClient is used. -func NewClient(store ClientStorage, client *http.Client) *Client { - if client == nil { - client = http.DefaultClient +func WithClient(client *http.Client) Option { + return func(c *Client) { + c.client = client } - t := depclient.NewTransport(client.Transport, client, store, nil) - client = depclient.NewClient(client, t) - return &Client{ +} + +// NewClient creates new Client and reads authentication and config data from store. +func NewClient(store ClientStorage, opts ...Option) *Client { + c := &Client{ store: store, - client: client, + client: http.DefaultClient, + ua: UserAgent, + } + for _, opt := range opts { + opt(c) } + t := depclient.NewTransport(c.client.Transport, c.client, store, nil) + c.client = depclient.NewClient(c.client, t) + return c } // do executes the HTTP request using the client's HTTP client which @@ -106,7 +124,9 @@ func (c *Client) do(ctx context.Context, name, method, path string, in interface if err != nil { return err } - req.Header.Set("User-Agent", userAgent) + if c.ua != "" { + req.Header.Set("User-Agent", c.ua) + } if body != nil { req.Header.Set("Content-Type", mediaType) }