From ea6ee34264696a90410b51aff4ae32bb832651c6 Mon Sep 17 00:00:00 2001 From: Josue Kouka Date: Sat, 6 Jan 2024 04:44:16 -0800 Subject: [PATCH] Add common http methods to client --- README.md | 20 +++++++++- client.go | 59 ++++++++++++++++++++++++++++- client_test.go | 100 ++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 176 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index e3b570d..9c242b7 100644 --- a/README.md +++ b/README.md @@ -48,8 +48,26 @@ func main() { } ``` +Common *http verbs(HEAD, OPTIONS, GET, HEAD, POST, PATCH, DELETE)* are also supported +```go +package main + +import ( + "github.com/davesavic/clink" + "encoding/json" +) + +func main() { + client := clink.NewClient() + resp, err := client.Get("https://httpbin.org/get") + // .... + payload, err := json.Marshal(map[string]string{"username": "yumi"}) + resp, err := client.Post("https://httpbin.org/post", payload) +} +``` + ### Examples For more examples, see the [examples](https://github.com/davesavic/clink/tree/master/examples) directory. ### Contributing -Contributions to Clink are welcome! If you find a bug, have a feature request, or want to contribute code, please open an issue or submit a pull request. \ No newline at end of file +Contributions to Clink are welcome! If you find a bug, have a feature request, or want to contribute code, please open an issue or submit a pull request. diff --git a/client.go b/client.go index e1a535c..bf9d171 100644 --- a/client.go +++ b/client.go @@ -4,10 +4,11 @@ import ( "encoding/base64" "encoding/json" "fmt" - "golang.org/x/time/rate" "io" "net/http" "time" + + "golang.org/x/time/rate" ) type Client struct { @@ -69,6 +70,62 @@ func (c *Client) Do(req *http.Request) (*http.Response, error) { return resp, nil } +func (c *Client) Head(url string) (*http.Response, error) { + req, err := http.NewRequest(http.MethodHead, url, nil) + if err != nil { + return nil, err + } + return c.Do(req) +} + +func (c *Client) Options(url string) (*http.Response, error) { + req, err := http.NewRequest(http.MethodOptions, url, nil) + if err != nil { + return nil, err + } + return c.Do(req) +} + +func (c *Client) Get(url string) (*http.Response, error) { + req, err := http.NewRequest(http.MethodGet, url, nil) + if err != nil { + return nil, err + } + return c.Do(req) +} + +func (c *Client) Post(url string, body io.Reader) (*http.Response, error) { + req, err := http.NewRequest(http.MethodPost, url, body) + if err != nil { + return nil, err + } + return c.Do(req) +} + +func (c *Client) Put(url string, body io.Reader) (*http.Response, error) { + req, err := http.NewRequest(http.MethodPut, url, body) + if err != nil { + return nil, err + } + return c.Do(req) +} + +func (c *Client) Patch(url string, body io.Reader) (*http.Response, error) { + req, err := http.NewRequest(http.MethodPatch, url, body) + if err != nil { + return nil, err + } + return c.Do(req) +} + +func (c *Client) Delete(url string) (*http.Response, error) { + req, err := http.NewRequest(http.MethodDelete, url, nil) + if err != nil { + return nil, err + } + return c.Do(req) +} + type Option func(*Client) // WithClient sets the http client for the client. diff --git a/client_test.go b/client_test.go index bd06ef0..9851a80 100644 --- a/client_test.go +++ b/client_test.go @@ -3,13 +3,14 @@ package clink_test import ( "encoding/base64" "encoding/json" - "github.com/davesavic/clink" "io" "net/http" "net/http/httptest" "strings" "testing" "time" + + "github.com/davesavic/clink" ) func TestNewClient(t *testing.T) { @@ -252,6 +253,103 @@ func TestClient_Do(t *testing.T) { } } +func TestClient_Methods(t *testing.T) { + serverFunc := func() *httptest.Server { + return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Add("X-Method", r.Method) + })) + } + resultFunc := func(r *http.Response, m string) bool { + return r.Header.Get("X-Method") == m + } + testCases := []struct { + name string + method string + body io.Reader + setupServer func() *httptest.Server + resultFunc func(*http.Response, string) bool + }{ + { + name: "successful head response", + method: http.MethodHead, + setupServer: serverFunc, + resultFunc: resultFunc, + }, + { + name: "successful options response", + method: http.MethodOptions, + setupServer: serverFunc, + resultFunc: resultFunc, + }, + { + name: "successful get response", + method: http.MethodGet, + setupServer: serverFunc, + resultFunc: resultFunc, + }, + { + name: "successful post response", + method: http.MethodPost, + setupServer: serverFunc, + resultFunc: resultFunc, + }, + { + name: "successful put response", + method: http.MethodPut, + setupServer: serverFunc, + resultFunc: resultFunc, + }, + { + name: "successful patch response", + method: http.MethodPatch, + setupServer: serverFunc, + resultFunc: resultFunc, + }, + { + name: "successful delete response", + method: http.MethodDelete, + setupServer: serverFunc, + resultFunc: resultFunc, + }, + } + + call := func(c *clink.Client, method, url string, body io.Reader) (*http.Response, error) { + switch method { + case http.MethodHead: + return c.Head(url) + case http.MethodOptions: + return c.Options(url) + case http.MethodGet: + return c.Get(url) + case http.MethodPost: + return c.Post(url, body) + case http.MethodPut: + return c.Put(url, body) + case http.MethodPatch: + return c.Patch(url, body) + case http.MethodDelete: + return c.Delete(url) + } + return nil, nil + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + server := tc.setupServer() + defer server.Close() + c := clink.NewClient(clink.WithClient(server.Client())) + if c == nil { + t.Error("expected client to be created") + } + resp, _ := call(c, tc.method, server.URL, tc.body) + if !tc.resultFunc(resp, tc.method) { + t.Errorf("expected result to be successful") + } + + }) + } +} + func TestClient_ResponseToJson(t *testing.T) { testCases := []struct { name string