boilerplate-go/utils/apiUtils.go

169 lines
3.8 KiB
Go

package utils
import (
"bytes"
"crypto/tls"
"encoding/json"
"fmt"
"github.com/pkg/errors"
"gitlab.com/arkadooti.sarkar/go-boilerplate/core/appcontext"
"gitlab.com/arkadooti.sarkar/go-boilerplate/core/log"
"io"
"io/ioutil"
"net/http"
"net/url"
"time"
)
const (
RequestID = "requestId"
)
var Client HTTPClient
// HTTPClient interface
type HTTPClient interface {
Do(req *http.Request) (*http.Response, error)
}
func init() {
Client = &http.Client{
Transport: &http.Transport{
DisableKeepAlives: true,
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
},
Timeout: time.Duration(35) * time.Second,
}
}
// ApiParam api parameters
type ApiParam struct {
Url string
Type string
Query map[string]string
Headers map[string]string
Body io.Reader
}
type responseMetaData struct { //to-do: it must be renamed to a generic response struct
Code int `json:"code,omitempty"`
Message string `json:"message"`
}
func (apiParam *ApiParam) CallAPI(ctx appcontext.AppContext, dst interface{}) error {
reqMethod := "GET"
if apiParam.Type != "" {
reqMethod = apiParam.Type
}
if apiParam.Url == "" {
return errors.New("unable to make request, url is missing")
}
u, err := url.Parse(apiParam.Url)
if err != nil {
return err
}
q := u.Query()
for key, val := range apiParam.Query {
q.Set(key, fmt.Sprintf("%v", val))
}
u.RawQuery = q.Encode()
req, err := http.NewRequest(reqMethod, u.String(), apiParam.Body)
if req != nil {
_, reqIDFound := apiParam.Headers[RequestID]
if !reqIDFound {
req.Header.Set(RequestID, ctx.RequestID)
}
for headerKey, headerVal := range apiParam.Headers {
req.Header.Set(headerKey, headerVal)
}
}
resp, err := Client.Do(req)
if resp != nil {
defer func(Body io.ReadCloser) {
err := Body.Close()
if err != nil {
log.GenericError(ctx, err, nil)
}
}(resp.Body)
}
if err != nil {
return err
}
if resp.StatusCode >= 200 && resp.StatusCode < 300 {
if dst != nil {
err = json.NewDecoder(resp.Body).Decode(dst)
if err != nil {
return errors.WithMessage(err, "failed to decode response\",")
}
}
_, err := io.Copy(ioutil.Discard, resp.Body)
if err != nil {
log.GenericError(ctx, err, nil)
}
return nil
}
bodyError := fmt.Errorf("unable to make request, error in statusCode: " + resp.Status)
if resp.Body != nil {
body, _ := ioutil.ReadAll(resp.Body)
bodyError = errors.New(string(body))
}
return bodyError
}
func ReturnResponse(ctx appcontext.AppContext, w http.ResponseWriter, statusCode int, response interface{}) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(statusCode)
var buf = new(bytes.Buffer)
enc := json.NewEncoder(buf)
err := enc.Encode(response)
if err != nil {
log.GenericError(ctx, err)
}
_, err = w.Write(buf.Bytes())
if err != nil {
log.GenericError(ctx, err)
}
}
func ReturnOKResponse(ctx appcontext.AppContext, w http.ResponseWriter, response interface{}) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
var buf = new(bytes.Buffer)
enc := json.NewEncoder(buf)
err := enc.Encode(response)
if err != nil {
log.GenericError(ctx, err)
}
_, err = w.Write(buf.Bytes())
if err != nil {
log.GenericError(ctx, err)
}
}
func ReturnErrorResponse(ctx appcontext.AppContext, w http.ResponseWriter, responseErrorMessage string, statusCode int, logError error, fields ...log.FieldsMap) {
var buf = new(bytes.Buffer)
encoder := json.NewEncoder(buf)
if logError != nil {
if len(fields) > 0 {
log.GenericError(ctx, logError, fields[0])
} else {
log.GenericError(ctx, logError, nil)
}
}
err := encoder.Encode(responseMetaData{Message: responseErrorMessage})
if err != nil {
log.GenericError(ctx, err)
}
w.WriteHeader(statusCode)
_, err = w.Write(buf.Bytes())
if err != nil {
log.GenericError(ctx, err)
}
}