git.sr.ht/~pingoo/stdx@v0.0.0-20240218134121-094174641f6e/postmark/client.go (about) 1 package postmark 2 3 import ( 4 "bytes" 5 "context" 6 "encoding/json" 7 "errors" 8 "io" 9 "net/http" 10 11 "git.sr.ht/~pingoo/stdx/httpx" 12 ) 13 14 type Client struct { 15 httpClient *http.Client 16 accountApiToken string 17 baseURL string 18 } 19 20 func NewClient(accountApiToken string, httpClient *http.Client) *Client { 21 if httpClient == nil { 22 httpClient = httpx.DefaultClient() 23 } 24 25 return &Client{ 26 httpClient: httpClient, 27 accountApiToken: accountApiToken, 28 baseURL: "https://api.postmarkapp.com", 29 } 30 } 31 32 type requestParams struct { 33 Method string 34 URL string 35 Payload interface{} 36 ServerToken *string 37 } 38 39 func (client *Client) request(ctx context.Context, params requestParams, dst interface{}) error { 40 url := client.baseURL + params.URL 41 42 req, err := http.NewRequestWithContext(ctx, params.Method, url, nil) 43 if err != nil { 44 return err 45 } 46 47 if params.Payload != nil { 48 payloadData, err := json.Marshal(params.Payload) 49 if err != nil { 50 return err 51 } 52 req.Body = io.NopCloser(bytes.NewBuffer(payloadData)) 53 } 54 55 req.Header.Add(httpx.HeaderAccept, httpx.MediaTypeJson) 56 req.Header.Add(httpx.HeaderContentType, httpx.MediaTypeJson) 57 58 if params.ServerToken != nil { 59 req.Header.Add("X-Postmark-Server-Token", *params.ServerToken) 60 } else { 61 req.Header.Add("X-Postmark-Account-Token", client.accountApiToken) 62 } 63 64 res, err := client.httpClient.Do(req) 65 if err != nil { 66 return err 67 } 68 defer res.Body.Close() 69 70 body, err := io.ReadAll(res.Body) 71 if err != nil { 72 return err 73 } 74 75 if dst == nil || res.StatusCode > 399 { 76 var apiRes APIError 77 err = json.Unmarshal(body, &apiRes) 78 if err != nil { 79 return err 80 } 81 if apiRes.ErrorCode != 0 { 82 err = errors.New(apiRes.Message) 83 return err 84 } 85 } else { 86 err = json.Unmarshal(body, dst) 87 } 88 89 return err 90 } 91 92 type APIError struct { 93 ErrorCode int64 94 Message string 95 } 96 97 func (res APIError) Error() string { 98 return res.Message 99 }