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) } }