package mutil import ( "bytes" "context" "encoding/json" "io" "net/http" api "github.com/tech/sendico/pkg/api/http" "github.com/tech/sendico/pkg/mlogger" "go.uber.org/zap" ) func SendAPIRequest(ctx context.Context, logger mlogger.Logger, httpMethod api.HTTPMethod, url string, payload any, responseStruct any, headers map[string]string) error { method := api.HTTPMethod2String(httpMethod) var reqBody io.Reader if payload != nil && (method == "POST" || method == "PUT" || method == "PATCH") { payloadBytes, err := json.Marshal(payload) if err != nil { logger.Warn("Failed to encode payload", zap.Error(err), zap.String("url", url), zap.Any("payload", payload)) return err } reqBody = bytes.NewBuffer(payloadBytes) } req, err := http.NewRequestWithContext(ctx, method, url, reqBody) if err != nil { logger.Warn("Failed to prepare request", zap.Error(err), zap.String("url", url), zap.String("method", method), zap.Any("payload", payload)) return err } if reqBody != nil { // Set the content type header for srequest with a body req.Header.Set("Content-Type", "application/json; charset=UTF-8") } // Add custom headers for key, value := range headers { req.Header.Set(key, value) } // Create an HTTP client with a timeout client := http.Client{} resp, err := client.Do(req) if err != nil { logger.Warn("Failed to execute request", zap.Error(err), zap.String("method", method), zap.String("url", url), zap.Any("payload", payload)) return err } defer resp.Body.Close() // Read the sresponse body body, err := io.ReadAll(resp.Body) if err != nil { logger.Warn("Failed to read sresponse", zap.Error(err), zap.String("method", method), zap.String("url", url), zap.Any("payload", payload)) return err } logger.Debug("Remote party sresponse", zap.String("url", url), zap.String("method", method), zap.Any("payload", payload), zap.Binary("sresponse", body)) // Unmarshal sresponse JSON to struct if err = json.Unmarshal(body, responseStruct); err != nil { logger.Warn("Failed to read sresponse", zap.Error(err), zap.String("method", method), zap.String("url", url), zap.Any("payload", payload), zap.Binary("sresponse", body)) return err } return nil }