From bd54b32b8816e5adf400e860dfbaac67c1b43571 Mon Sep 17 00:00:00 2001 From: bhanur Date: Fri, 12 Jul 2024 22:38:21 +0530 Subject: [PATCH] Initial Commit --- README.md | 15 ++++++++++++++- client/client.go | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ client/delete.go | 25 +++++++++++++++++++++++++ client/get.go | 29 +++++++++++++++++++++++++++++ client/post.go | 30 ++++++++++++++++++++++++++++++ client/put.go | 28 ++++++++++++++++++++++++++++ client/types.go | 20 ++++++++++++++++++++ client/utils.go | 26 ++++++++++++++++++++++++++ go.mod | 3 +++ 9 files changed, 223 insertions(+), 1 deletion(-) create mode 100644 client/client.go create mode 100644 client/delete.go create mode 100644 client/get.go create mode 100644 client/post.go create mode 100644 client/put.go create mode 100644 client/types.go create mode 100644 client/utils.go create mode 100644 go.mod diff --git a/README.md b/README.md index 987204e..85a84c8 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,15 @@ # rest -A generic rest client for making go http requests +A simple wrapper around http client to make restful requests easier. + +- An example usage for a post request +```go +client := DefaultClient() +client.URL = "http://example.com" +client.Headers = map[string]string{ + "ContentType": "application/json" + "Authorization":"Bearer token" +} +client.Body = bytes.NewReader([]byte(`{"key": "value"}`)) +client.Strategy = PostRequest{} +client.Send() +``` diff --git a/client/client.go b/client/client.go new file mode 100644 index 0000000..984fce2 --- /dev/null +++ b/client/client.go @@ -0,0 +1,48 @@ +package client + +// NewClient creates a new Client struct with the provided URL and headers. +// the default timeout is 30 seconds +// the default method is GET +// the default Body is an empty byte slice +func NewClient(url string, headers map[string]string) *Client { + return &Client{ + URL: url, + Headers: headers, + Body: []byte{}, + Timeout: 10, + Strategy: &GetRequest{}, + } +} + +// DefaultClient creates a new Client struct with default values. +// URL: empty string +// headers: nil +// timeout: 10 seconds +// Body: empty byte slice +// Strategy: nil +func DefaultClient() *Client { + return &Client{ + URL: "", + Headers: nil, + Body: []byte{}, + Timeout: 10, + Strategy: nil, + } +} + +// CreateClientWithTimeout creates a new http.Client with the provided timeout +func CreateClientWithTimeout(timeout int) *Client { + client := DefaultClient() + client.Timeout = timeout + return client +} + +// SetStrategy allows setting the current request strategy +func (c *Client) SetStrategy(s RequestMethod) { + c.Strategy = s +} + +// Send delegates the request handling to the strategy +func (c *Client) Send(url string, body []byte, headers map[string]string, timeout int) (*Response, error) { + return c.Strategy.Do(url, body, headers, timeout) +} diff --git a/client/delete.go b/client/delete.go new file mode 100644 index 0000000..a580a49 --- /dev/null +++ b/client/delete.go @@ -0,0 +1,25 @@ +package client + +import ( + "net/http" +) + +type DeleteRequest struct{} + +func (d *DeleteRequest) Do(url string, headers map[string]string, timeout int) (*Response, error) { + req, err := http.NewRequest(http.MethodDelete, url, nil) + if err != nil { + return nil, err + } + + for key, value := range headers { + req.Header.Add(key, value) + } + + client := createClient(timeout) + resp, err := client.Do(req) + if err != nil { + return nil, err + } + return handleResponse(resp) +} diff --git a/client/get.go b/client/get.go new file mode 100644 index 0000000..3a33643 --- /dev/null +++ b/client/get.go @@ -0,0 +1,29 @@ +package client + +import ( + "net/http" +) + +// GetRequest strategy +type GetRequest struct{} + +// Do makes a generic GET request to the specified URL with the provided headers. +// It returns the response body as a byte slice and any error encountered. +func (g *GetRequest) Do(url string, body []byte, headers map[string]string, timeout int) (*Response, error) { + req, err := http.NewRequest(http.MethodGet, url, nil) + if err != nil { + return nil, err + } + + // Add headers to the request + for key, value := range headers { + req.Header.Add(key, value) + } + + client := createClient(timeout) + resp, err := client.Do(req) + if err != nil { + return nil, err + } + return handleResponse(resp) +} diff --git a/client/post.go b/client/post.go new file mode 100644 index 0000000..66f306b --- /dev/null +++ b/client/post.go @@ -0,0 +1,30 @@ +package client + +import ( + "bytes" + "net/http" +) + +// PostRequest strategy +type PostRequest struct{} + +// Do makes a generic POST request to the specified URL with the provided body and headers. +// It returns a Response struct and any error encountered. +func (p *PostRequest) Do(url string, body []byte, headers map[string]string, timeout int) (*Response, error) { + reqBody := bytes.NewBuffer(body) + req, err := http.NewRequest(http.MethodPost, url, reqBody) + if err != nil { + return nil, err + } + + for key, value := range headers { + req.Header.Add(key, value) + } + + client := createClient(timeout) + resp, err := client.Do(req) + if err != nil { + return nil, err + } + return handleResponse(resp) +} diff --git a/client/put.go b/client/put.go new file mode 100644 index 0000000..612d279 --- /dev/null +++ b/client/put.go @@ -0,0 +1,28 @@ +package client + +import ( + "bytes" + "net/http" +) + +// PutRequest strategy +type PutRequest struct{} + +func (p *PutRequest) Do(url string, body []byte, headers map[string]string, timeout int) (*Response, error) { + reqBody := bytes.NewBuffer(body) + req, err := http.NewRequest(http.MethodPut, url, reqBody) + if err != nil { + return nil, err + } + + for key, value := range headers { + req.Header.Add(key, value) + } + + client := createClient(timeout) + resp, err := client.Do(req) + if err != nil { + return nil, err + } + return handleResponse(resp) +} diff --git a/client/types.go b/client/types.go new file mode 100644 index 0000000..46c2b4c --- /dev/null +++ b/client/types.go @@ -0,0 +1,20 @@ +package client + +type Client struct { + URL string + Headers map[string]string + Body []byte + Timeout int + Strategy RequestMethod +} + +type Response struct { + StatusCode int + Body []byte + Error error +} + +// RequestMethod defines the interface for HTTP request strategies. +type RequestMethod interface { + Do(url string, body []byte, headers map[string]string, timeout int) (*Response, error) +} diff --git a/client/utils.go b/client/utils.go new file mode 100644 index 0000000..6423f9e --- /dev/null +++ b/client/utils.go @@ -0,0 +1,26 @@ +package client + +import ( + "io" + "net/http" + "time" +) + +func createClient(timeout int) *http.Client { + return &http.Client{ + Timeout: time.Duration(timeout) * time.Second, + } +} + +func handleResponse(resp *http.Response) (*Response, error) { + defer resp.Body.Close() + body, err := io.ReadAll(resp.Body) + if err != nil { + return nil, err + } + return &Response{ + StatusCode: resp.StatusCode, + Body: body, + Error: nil, // Error handling could be more nuanced + }, nil +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..f277c46 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module rest + +go 1.22.5