Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

treat non-JSON responses well #24

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module github.com/getlantern/mandrill

go 1.18
66 changes: 47 additions & 19 deletions mandrill.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,10 @@ package mandrill

import (
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"net/http"
)
Expand Down Expand Up @@ -219,14 +221,14 @@ func ClientWithKey(key string) *Client {
}
}

func (c *Client) Ping() (pong string, err error) {
func (c *Client) Ping(ctx context.Context) (pong string, err error) {
var data struct {
Key string `json:"key"`
}

data.Key = c.Key

body, err := c.sendApiRequest(data, "users/ping.json")
body, err := c.sendApiRequest(ctx, data, "users/ping.json")
if err != nil {
return pong, err
}
Expand All @@ -236,7 +238,9 @@ func (c *Client) Ping() (pong string, err error) {
}

// MessagesSend sends a message via an API client
func (c *Client) MessagesSend(message *Message) (responses []*Response, err error) {
func (c *Client) MessagesSend(
ctx context.Context,
message *Message) (responses []*Response, err error) {

var data struct {
Key string `json:"key"`
Expand All @@ -255,11 +259,15 @@ func (c *Client) MessagesSend(message *Message) (responses []*Response, err erro
data.IPPool = message.IPPool
data.SendAt = message.SendAt

return c.sendMessagePayload(data, "messages/send.json")
return c.sendMessagePayload(ctx, data, "messages/send.json")
}

// MessagesSendTemplate sends a message using a Mandrill template
func (c *Client) MessagesSendTemplate(message *Message, templateName string, contents interface{}) (responses []*Response, err error) {
func (c *Client) MessagesSendTemplate(
ctx context.Context,
message *Message,
templateName string,
contents interface{}) (responses []*Response, err error) {

var data struct {
Key string `json:"key"`
Expand All @@ -282,10 +290,13 @@ func (c *Client) MessagesSendTemplate(message *Message, templateName string, con
data.IPPool = message.IPPool
data.SendAt = message.SendAt

return c.sendMessagePayload(data, "messages/send-template.json")
return c.sendMessagePayload(ctx, data, "messages/send-template.json")
}

func (c *Client) sendMessagePayload(data interface{}, path string) (responses []*Response, err error) {
func (c *Client) sendMessagePayload(
ctx context.Context,
data interface{},
path string) (responses []*Response, err error) {

if c.Key == "SANDBOX_SUCCESS" {
return []*Response{}, nil
Expand All @@ -295,7 +306,7 @@ func (c *Client) sendMessagePayload(data interface{}, path string) (responses []
return nil, errors.New("SANDBOX_ERROR")
}

body, err := c.sendApiRequest(data, path)
body, err := c.sendApiRequest(ctx, data, path)
if err != nil {
return responses, err
}
Expand All @@ -304,27 +315,44 @@ func (c *Client) sendMessagePayload(data interface{}, path string) (responses []
return responses, err
}

func (c *Client) sendApiRequest(data interface{}, path string) (body []byte, err error) {
payload, _ := json.Marshal(data)
func (c *Client) sendApiRequest(
ctx context.Context,
data interface{},
path string) (body []byte, err error) {
payload, err := json.Marshal(data)
if err != nil {
return nil, fmt.Errorf("while marshalling JSON: %s", err)
}

resp, err := c.HTTPClient.Post(c.BaseURL+path, "application/json", bytes.NewReader(payload))
req, err := http.NewRequestWithContext(ctx, "POST", c.BaseURL+path, bytes.NewBuffer(payload))
if err != nil {
return nil, fmt.Errorf("while creating request: %s", err)
}
req.Header.Set("Content-Type", "application/json")
resp, err := c.HTTPClient.Do(req)
if err != nil {
return body, err
return nil, fmt.Errorf("while sending request: %s", err)
}

defer resp.Body.Close()
body, err = ioutil.ReadAll(resp.Body)
if err != nil {
return body, err
return nil, fmt.Errorf("while reading response: %s", err)
}

if resp.StatusCode >= 400 {
resError := &Error{}
resError := &Error{
Status: resp.Status,
Code: resp.StatusCode,
}
err = json.Unmarshal(body, resError)
return body, resError
if err != nil {
return nil, fmt.Errorf("HTTP %v: %v", resp.StatusCode, string(body))
}
return nil, resError
}

return body, err
return body, nil
}

// AddRecipient appends a recipient to the message
Expand All @@ -339,14 +367,14 @@ func (m *Message) AddRecipient(email string, name string, sendType string) {
func ConvertMapToVariables(i interface{}) []*Variable {
imap := map[string]interface{}{}

switch i.(type) {
switch i := i.(type) {
// Handle older API for passing just map[string]string
case map[string]string:
for k, v := range i.(map[string]string) {
for k, v := range i {
imap[k] = v
}
case map[string]interface{}:
imap, _ = i.(map[string]interface{})
imap = i
default:
return []*Variable{}
}
Expand Down
23 changes: 15 additions & 8 deletions mandrill_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package mandrill

import (
"context"
"fmt"
"net/http"
"net/http/httptest"
Expand Down Expand Up @@ -52,7 +53,11 @@ func Test_ClientWithKey(t *testing.T) {
func Test_MessagesSendTemplate_Success(t *testing.T) {
server, m := testTools(200, `[{"email":"[email protected]","status":"sent","reject_reason":"hard-bounce","_id":"1"}]`)
defer server.Close()
responses, err := m.MessagesSendTemplate(&Message{}, "cheese", map[string]string{"name": "bob"})
responses, err := m.MessagesSendTemplate(
context.Background(),
&Message{},
"cheese",
map[string]string{"name": "bob"})

expect(t, len(responses), 1)
expect(t, err, nil)
Expand All @@ -69,7 +74,9 @@ func Test_MessagesSendTemplate_Success(t *testing.T) {
func Test_MessagesSendTemplate_Fail(t *testing.T) {
server, m := testTools(400, `{"status":"error","code":12,"name":"Unknown_Subaccount","message":"No subaccount exists with the id 'customer-123'"}`)
defer server.Close()
responses, err := m.MessagesSendTemplate(&Message{}, "cheese", map[string]string{"name": "bob"})
responses, err := m.MessagesSendTemplate(
context.Background(),
&Message{}, "cheese", map[string]string{"name": "bob"})

expect(t, len(responses), 0)

Expand All @@ -87,7 +94,7 @@ func Test_MessagesSendTemplate_Fail(t *testing.T) {
func Test_MessageSend_Success(t *testing.T) {
server, m := testTools(200, `[{"email":"[email protected]","status":"sent","reject_reason":"hard-bounce","_id":"1"}]`)
defer server.Close()
responses, err := m.MessagesSend(&Message{})
responses, err := m.MessagesSend(context.Background(), &Message{})

expect(t, len(responses), 1)
expect(t, err, nil)
Expand All @@ -104,7 +111,7 @@ func Test_MessageSend_Success(t *testing.T) {
func Test_MessageSend_Fail(t *testing.T) {
server, m := testTools(400, `{"status":"error","code":12,"name":"Unknown_Subaccount","message":"No subaccount exists with the id 'customer-123'"}`)
defer server.Close()
responses, err := m.MessagesSend(&Message{})
responses, err := m.MessagesSend(context.Background(), &Message{})

expect(t, len(responses), 0)

Expand All @@ -122,7 +129,7 @@ func Test_MessageSend_Fail(t *testing.T) {
func Test_Ping_Success(t *testing.T) {
server, m := testTools(200, `"PONG!"`)
defer server.Close()
response, err := m.Ping()
response, err := m.Ping(context.Background())

expect(t, response, "PONG!")
expect(t, err, nil)
Expand All @@ -131,7 +138,7 @@ func Test_Ping_Success(t *testing.T) {
func Test_Ping_Fail(t *testing.T) {
server, m := testTools(400, `{"status":"error","code":-1,"name":"Invalid_Key","message":"Invalid API key"}`)
defer server.Close()
response, err := m.Ping()
response, err := m.Ping(context.Background())

expect(t, response, "")

Expand All @@ -148,13 +155,13 @@ func Test_Ping_Fail(t *testing.T) {

func Test_SANDBOX_SUCCESS(t *testing.T) {
client := ClientWithKey("SANDBOX_SUCCESS")
_, err := client.MessagesSend(&Message{})
_, err := client.MessagesSend(context.Background(), &Message{})
expect(t, err, nil)
}

func Test_SANDBOX_ERROR(t *testing.T) {
client := ClientWithKey("SANDBOX_ERROR")
_, err := client.MessagesSend(&Message{})
_, err := client.MessagesSend(context.Background(), &Message{})
refute(t, err, nil)
}

Expand Down