git.sr.ht/~pingoo/stdx@v0.0.0-20240218134121-094174641f6e/mailgun/client.go (about)

     1  package mailgun
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"encoding/json"
     7  	"io"
     8  	"net/http"
     9  
    10  	"git.sr.ht/~pingoo/stdx/httpx"
    11  )
    12  
    13  type Client struct {
    14  	httpClient    *http.Client
    15  	apiKey        string
    16  	globalBaseURL string
    17  	euBaseURL     string
    18  }
    19  
    20  func NewClient(apiKey string, httpClient *http.Client) *Client {
    21  	if httpClient == nil {
    22  		httpClient = httpx.DefaultClient()
    23  	}
    24  
    25  	return &Client{
    26  		httpClient:    httpClient,
    27  		apiKey:        apiKey,
    28  		globalBaseURL: "https://api.mailgun.net",
    29  		euBaseURL:     "https://api.eu.mailgun.net",
    30  	}
    31  }
    32  
    33  type requestParams struct {
    34  	Method  string
    35  	URL     string
    36  	Payload interface{}
    37  }
    38  
    39  func (client *Client) request(ctx context.Context, params requestParams, dst interface{}) error {
    40  	url := client.euBaseURL
    41  	// url := client.globalBaseURL
    42  	// if !global {
    43  	// 	url = client.euBaseURL
    44  	// }
    45  	url += params.URL
    46  
    47  	req, err := http.NewRequestWithContext(ctx, params.Method, url, nil)
    48  	if err != nil {
    49  		return err
    50  	}
    51  
    52  	if params.Payload != nil {
    53  		payloadData, err := json.Marshal(params.Payload)
    54  		if err != nil {
    55  			return err
    56  		}
    57  		req.Body = io.NopCloser(bytes.NewBuffer(payloadData))
    58  	}
    59  
    60  	req.Header.Add(httpx.HeaderAccept, httpx.MediaTypeJson)
    61  	req.Header.Add(httpx.HeaderContentType, httpx.MediaTypeJson)
    62  	req.Header.Add(httpx.HeaderUserAgent, "mailgun-go/4.6.1")
    63  	req.SetBasicAuth("api", client.apiKey)
    64  
    65  	res, err := client.httpClient.Do(req)
    66  	if err != nil {
    67  		return err
    68  	}
    69  	defer res.Body.Close()
    70  
    71  	body, err := io.ReadAll(res.Body)
    72  	if err != nil {
    73  		return err
    74  	}
    75  
    76  	if res.StatusCode >= 400 {
    77  		var apiErr APIError
    78  
    79  		err = json.Unmarshal(body, &apiErr)
    80  		if err != nil {
    81  			return err
    82  		}
    83  
    84  		return apiErr
    85  	} else if dst != nil {
    86  		err = json.Unmarshal(body, dst)
    87  	}
    88  
    89  	return err
    90  }
    91  
    92  // See https://github.com/mailgun/mailgun.js/blob/master/lib/Types/Common/Error.ts
    93  // and https://github.com/mailgun/mailgun.js/tree/master/lib/Classes
    94  // and https://github.com/mailgun/mailgun.js/blob/master/lib/Types/Common/ApiResponse.ts
    95  type APIError struct {
    96  	Message string `json:"message"`
    97  }
    98  
    99  func (res APIError) Error() string {
   100  	return res.Message
   101  }