From 6d615771cb9f1ac92cf3ce9ec2f4c46750b9b628 Mon Sep 17 00:00:00 2001 From: Vartan Benohanian Date: Sun, 24 Jan 2021 22:51:27 -0500 Subject: [PATCH] Use Credentials struct for NewClient Signed-off-by: Vartan Benohanian --- README.md | 10 +++++----- examples/submit-post/main.go | 5 ++--- reddit/reddit-options.go | 13 +------------ reddit/reddit-options_test.go | 27 +++++++++------------------ reddit/reddit.go | 23 +++++++++++++---------- reddit/reddit_test.go | 8 ++++---- 6 files changed, 34 insertions(+), 52 deletions(-) diff --git a/README.md b/README.md index 345891b..e2ec9d9 100644 --- a/README.md +++ b/README.md @@ -46,8 +46,8 @@ package main import "github.com/vartanbeno/go-reddit/reddit" func main() { - withCredentials := reddit.WithCredentials("id", "secret", "username", "password") - client, _ := reddit.NewClient(withCredentials) + credentials := reddit.Credentials{ID: "id", Secret: "secret", Username: "username", Password: "password"} + client, _ := reddit.NewClient(credentials) } ``` @@ -55,7 +55,7 @@ You can pass in a number of options to `NewClient` to further configure the clie ```go httpClient := &http.Client{Timeout: time.Second * 30} -client, _ := reddit.NewClient(withCredentials, reddit.WithHTTPClient(httpClient)) +client, _ := reddit.NewClient(credentials, reddit.WithHTTPClient(httpClient)) ``` ### Read-Only Mode @@ -69,10 +69,10 @@ client, _ := reddit.NewReadonlyClient() ## Examples
- Configure the client from environment variables. + Configure the client from environment variables. When using this option, it's ok to pass an empty struct for the credentials. ```go -client, _ := reddit.NewClient(reddit.FromEnv) +client, _ := reddit.NewClient(reddit.Credentials{}, reddit.FromEnv) ```
diff --git a/examples/submit-post/main.go b/examples/submit-post/main.go index e3f3632..c9c6ff1 100644 --- a/examples/submit-post/main.go +++ b/examples/submit-post/main.go @@ -17,9 +17,8 @@ func main() { } func run() (err error) { - withCredentials := reddit.WithCredentials("id", "secret", "username", "password") - - client, err := reddit.NewClient(withCredentials) + credentials := reddit.Credentials{ID: "id", Secret: "secret", Username: "username", Password: "password"} + client, err := reddit.NewClient(credentials) if err != nil { return } diff --git a/reddit/reddit-options.go b/reddit/reddit-options.go index c8bb19f..25d397b 100644 --- a/reddit/reddit-options.go +++ b/reddit/reddit-options.go @@ -7,20 +7,9 @@ import ( "os" ) -// Opt is a configuration option to initialize a client. +// Opt is used to further configure a client upon initialization. type Opt func(*Client) error -// WithCredentials sets the credentials used to authenticate with the Reddit API. -func WithCredentials(id, secret, username, password string) Opt { - return func(c *Client) error { - c.ID = id - c.Secret = secret - c.Username = username - c.Password = password - return nil - } -} - // WithHTTPClient sets the HTTP client which will be used to make requests. func WithHTTPClient(httpClient *http.Client) Opt { return func(c *Client) error { diff --git a/reddit/reddit-options_test.go b/reddit/reddit-options_test.go index db6a958..3db5ce8 100644 --- a/reddit/reddit-options_test.go +++ b/reddit/reddit-options_test.go @@ -10,53 +10,44 @@ import ( "github.com/stretchr/testify/require" ) -func TestWithCredentials(t *testing.T) { - c, err := NewClient(WithCredentials("id1", "secret1", "username1", "password1")) - require.NoError(t, err) - require.Equal(t, "id1", c.ID) - require.Equal(t, "secret1", c.Secret) - require.Equal(t, "username1", c.Username) - require.Equal(t, "password1", c.Password) -} - func TestWithHTTPClient(t *testing.T) { - _, err := NewClient(WithHTTPClient(nil)) + _, err := NewClient(Credentials{}, WithHTTPClient(nil)) require.EqualError(t, err, "*http.Client: cannot be nil") - _, err = NewClient(WithHTTPClient(&http.Client{})) + _, err = NewClient(Credentials{}, WithHTTPClient(&http.Client{})) require.NoError(t, err) } func TestWithUserAgent(t *testing.T) { - c, err := NewClient(WithUserAgent("test")) + c, err := NewClient(Credentials{}, WithUserAgent("test")) require.NoError(t, err) require.Equal(t, "test", c.UserAgent()) - c, err = NewClient(WithUserAgent("")) + c, err = NewClient(Credentials{}, WithUserAgent("")) require.NoError(t, err) require.Equal(t, fmt.Sprintf("golang:%s:v%s", libraryName, libraryVersion), c.UserAgent()) } func TestWithBaseURL(t *testing.T) { - c, err := NewClient(WithBaseURL(":")) + c, err := NewClient(Credentials{}, WithBaseURL(":")) urlErr, ok := err.(*url.Error) require.True(t, ok) require.Equal(t, "parse", urlErr.Op) baseURL := "http://localhost:8080" - c, err = NewClient(WithBaseURL(baseURL)) + c, err = NewClient(Credentials{}, WithBaseURL(baseURL)) require.NoError(t, err) require.Equal(t, baseURL, c.BaseURL.String()) } func TestWithTokenURL(t *testing.T) { - c, err := NewClient(WithTokenURL(":")) + c, err := NewClient(Credentials{}, WithTokenURL(":")) urlErr, ok := err.(*url.Error) require.True(t, ok) require.Equal(t, "parse", urlErr.Op) tokenURL := "http://localhost:8080/api/v1/access_token" - c, err = NewClient(WithTokenURL(tokenURL)) + c, err = NewClient(Credentials{}, WithTokenURL(tokenURL)) require.NoError(t, err) require.Equal(t, tokenURL, c.TokenURL.String()) } @@ -74,7 +65,7 @@ func TestFromEnv(t *testing.T) { os.Setenv("GO_REDDIT_CLIENT_PASSWORD", "password1") defer os.Unsetenv("GO_REDDIT_CLIENT_PASSWORD") - c, err := NewClient(FromEnv) + c, err := NewClient(Credentials{}, FromEnv) require.NoError(t, err) require.Equal(t, "id1", c.ID) require.Equal(t, "secret1", c.Secret) diff --git a/reddit/reddit.go b/reddit/reddit.go index 8b1b4d6..bafda0c 100644 --- a/reddit/reddit.go +++ b/reddit/reddit.go @@ -21,7 +21,7 @@ import ( const ( libraryName = "github.com/vartanbeno/go-reddit" - libraryVersion = "1.0.0" + libraryVersion = "2.0.0" defaultBaseURL = "https://oauth.reddit.com" defaultBaseURLReadonly = "https://reddit.com" @@ -49,7 +49,7 @@ func DefaultClient() *Client { // RequestCompletionCallback defines the type of the request callback function. type RequestCompletionCallback func(*http.Request, *http.Response) -// Credentials used to authenticate to make requests to the Reddit API. +// Credentials are used to authenticate to make requests to the Reddit API. type Credentials struct { ID string Secret string @@ -110,7 +110,7 @@ func newClient() *Client { baseURL, _ := url.Parse(defaultBaseURL) tokenURL, _ := url.Parse(defaultTokenURL) - client := &Client{BaseURL: baseURL, TokenURL: tokenURL} + client := &Client{client: &http.Client{}, BaseURL: baseURL, TokenURL: tokenURL} client.Account = &AccountService{client: client} client.Collection = &CollectionService{client: client} @@ -136,20 +136,23 @@ func newClient() *Client { } // NewClient returns a new Reddit API client. -// Use an Opt to configure the client credentials, such as WithCredentials or FromEnv. -func NewClient(opts ...Opt) (*Client, error) { +// Use an Opt to configure the client credentials, such as WithHTTPClient or WithUserAgent. +// If the FromEnv option is used with the correct environment variables, an empty struct can +// be passed in as the credentials, since they will be overridden. +func NewClient(credentials Credentials, opts ...Opt) (*Client, error) { client := newClient() + client.ID = credentials.ID + client.Secret = credentials.Secret + client.Username = credentials.Username + client.Password = credentials.Password + for _, opt := range opts { if err := opt(client); err != nil { return nil, err } } - if client.client == nil { - client.client = &http.Client{} - } - userAgentTransport := &userAgentTransport{ userAgent: client.UserAgent(), Base: client.client.Transport, @@ -168,7 +171,7 @@ func NewClient(opts ...Opt) (*Client, error) { // NewReadonlyClient returns a new read-only Reddit API client. // The client will have limited access to the Reddit API. -// Options that modify credentials (such as WithCredentials or FromEnv) won't have any effect on this client. +// Options that modify credentials (such as FromEnv) won't have any effect on this client. func NewReadonlyClient(opts ...Opt) (*Client, error) { client := newClient() client.BaseURL, _ = url.Parse(defaultBaseURLReadonly) diff --git a/reddit/reddit_test.go b/reddit/reddit_test.go index 01187e9..f119004 100644 --- a/reddit/reddit_test.go +++ b/reddit/reddit_test.go @@ -35,7 +35,7 @@ func setup(t testing.TB) (*Client, *http.ServeMux) { }) client, _ := NewClient( - WithCredentials("id1", "secret1", "user1", "password1"), + Credentials{"id1", "secret1", "user1", "password1"}, WithBaseURL(server.URL), WithTokenURL(server.URL+"/api/v1/access_token"), ) @@ -98,20 +98,20 @@ func testClientDefaults(t *testing.T, c *Client) { } func TestNewClient(t *testing.T) { - c, err := NewClient() + c, err := NewClient(Credentials{}) require.NoError(t, err) testClientDefaults(t, c) } func TestNewClient_Error(t *testing.T) { - _, err := NewClient() + _, err := NewClient(Credentials{}) require.NoError(t, err) errorOpt := func(c *Client) error { return errors.New("foo") } - _, err = NewClient(errorOpt) + _, err = NewClient(Credentials{}, errorOpt) require.EqualError(t, err, "foo") }