package request import ( "context" "fmt" "io" "log" "net/http" "net/url" ) // Request HTTP request type Request struct { Method string URL string Headers map[string]string Body io.Reader } // Response HTTP Response type Response struct { StatusCode int URL *url.URL Body []byte } // NewRequest initalises new http request func NewRequest(method, url string, headers map[string]string, body io.Reader) (req *Request) { return &Request{ Method: method, URL: url, Headers: headers, Body: body, } } func (request *Request) request(ctx context.Context, client *http.Client) (*http.Response, error) { req, err := http.NewRequestWithContext(ctx, request.Method, request.URL, request.Body) if err != nil { return nil, err } for k, v := range request.Headers { req.Header.Set(k, v) } return client.Do(req) } func response(statuscode int, path string, body []byte) *Response { url, err := url.Parse(path) if err != nil { log.Println(err) return &Response{statuscode, nil, body} } return &Response{statuscode, url, body} } // Do initiates http request func (request *Request) Do(ctx context.Context, client *http.Client) (*Response, error) { resp, err := request.request(ctx, client) if err != nil { return response(http.StatusInternalServerError, request.URL, nil), err } body, err := io.ReadAll(resp.Body) if err != nil { return response(http.StatusInternalServerError, request.URL, nil), err } defer resp.Body.Close() if resp.StatusCode == http.StatusOK { return response(resp.StatusCode, request.URL, body), nil } return response(resp.StatusCode, request.URL, nil), fmt.Errorf("request: %s - %d %s", request.URL, resp.StatusCode, http.StatusText(resp.StatusCode)) } // Get sends GET request func Get(ctx context.Context, url string, headers map[string]string) (*Response, error) { return NewRequest(http.MethodGet, url, headers, nil).Do(ctx, &http.Client{}) } // Post sends POST request func Post(ctx context.Context, url string, headers map[string]string, data io.Reader) (*Response, error) { return NewRequest(http.MethodPost, url, headers, data).Do(ctx, &http.Client{}) } // Put sends PUT request func Put(ctx context.Context, url string, headers map[string]string, data io.Reader) (*Response, error) { return NewRequest(http.MethodPut, url, headers, data).Do(ctx, &http.Client{}) } // Delete sends DELETE request func Delete(ctx context.Context, url string, headers map[string]string, data io.Reader) (*Response, error) { return NewRequest(http.MethodDelete, url, headers, data).Do(ctx, &http.Client{}) }