From f35032f06b43afef9bdc138c866a1f8c029be3ea Mon Sep 17 00:00:00 2001 From: jolheiser Date: Thu, 3 Sep 2020 12:33:44 -0500 Subject: [PATCH] Move to functional options and add context Signed-off-by: jolheiser --- hcaptcha.go | 46 ++++++++++++++++++++++++++++++++++++++++------ hcaptcha_test.go | 6 +++++- 2 files changed, 45 insertions(+), 7 deletions(-) diff --git a/hcaptcha.go b/hcaptcha.go index 39dc3a2..1f21f84 100644 --- a/hcaptcha.go +++ b/hcaptcha.go @@ -1,6 +1,7 @@ package hcaptcha import ( + "context" "encoding/json" "io/ioutil" "net/http" @@ -12,7 +13,8 @@ const verifyURL = "https://hcaptcha.com/siteverify" // Client is an hCaptcha client type Client struct { - HTTP *http.Client + ctx context.Context + http *http.Client secret string } @@ -23,15 +25,40 @@ type PostOptions struct { Sitekey string } +// ClientOption is a func to modify a new Client +type ClientOption func(*Client) + +// WithHTTP sets the http.Client of a Client +func WithHTTP(httpClient *http.Client) func(*Client) { + return func(hClient *Client) { + hClient.http = httpClient + } +} + +// WithContext sets the context.Context of a Client +func WithContext(ctx context.Context) func(*Client) { + return func(hClient *Client) { + hClient.ctx = ctx + } +} + // New returns a new hCaptcha Client -func New(secret string) (*Client, error) { +func New(secret string, options ...ClientOption) (*Client, error) { if strings.TrimSpace(secret) == "" { return nil, ErrMissingInputSecret } - return &Client{ - HTTP: http.DefaultClient, + + client := &Client{ + ctx: context.Background(), + http: http.DefaultClient, secret: secret, - }, nil + } + + for _, opt := range options { + opt(client) + } + + return client, nil } // Verify checks the response against the hCaptcha API @@ -51,7 +78,14 @@ func (c *Client) Verify(token string, opts PostOptions) (*Response, error) { post.Add("sitekey", opts.Sitekey) } - resp, err := c.HTTP.PostForm(verifyURL, post) + // Basically a copy of http.PostForm, but with a context + req, err := http.NewRequestWithContext(c.ctx, http.MethodPost, verifyURL, strings.NewReader(post.Encode())) + if err != nil { + return nil, err + } + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + + resp, err := c.http.Do(req) if err != nil { return nil, err } diff --git a/hcaptcha_test.go b/hcaptcha_test.go index d64538e..d5011b2 100644 --- a/hcaptcha_test.go +++ b/hcaptcha_test.go @@ -1,9 +1,11 @@ package hcaptcha import ( + "net/http" "os" "strings" "testing" + "time" ) const ( @@ -53,7 +55,9 @@ func TestCaptcha(t *testing.T) { for _, tc := range tt { t.Run(tc.Name, func(t *testing.T) { - client, err := New(tc.Secret) + client, err := New(tc.Secret, WithHTTP(&http.Client{ + Timeout: time.Second * 5, + })) if err != nil { // The only error that can be returned from creating a client if tc.Error == ErrMissingInputSecret && err == ErrMissingInputSecret { -- 2.40.1