Skip to content

Commit

Permalink
Use interface methods to segment services
Browse files Browse the repository at this point in the history
To simplify stubbing the Braze interface.
  • Loading branch information
Henrik Thorsell authored and HThorsell committed Jun 1, 2023
1 parent 8750533 commit 61e84f8
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 48 deletions.
82 changes: 49 additions & 33 deletions braze.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,44 +18,74 @@ const (

// Braze defines the Braze REST API client interface.
type Braze interface {
UsersEndpoint
Users() UsersEndpoint
Messaging() MessagingEndpoint
PreferenceCenter() PreferenceCenterEndpoint
}

// Client implements Braze REST API client.
type Client struct {
baseURL *url.URL
apiKey string
userAgent string
httpClient *http.Client

// TODO
// Export ExportService
// Email EmailService
// Subscription SubscriptionService
// Templates TemplatesService

Messaging MessagingEndpoint
Users UsersEndpoint
PreferenceCenter PreferenceCenterEndpoint
http *httpClient

messaging MessagingEndpoint
users UsersEndpoint
preferenceCenter PreferenceCenterEndpoint
}

type httpClient struct {
baseURL *url.URL
apiKey string
userAgent string
httpClient *http.Client
}

func (c *Client) Users() UsersEndpoint {
return c.users
}

func (c *Client) Messaging() MessagingEndpoint {
return c.messaging
}

func (c *Client) PreferenceCenter() PreferenceCenterEndpoint {
return c.preferenceCenter
}

// NewClient sets up a new Braze client.
func NewClient(opts ...ClientOption) (*Client, error) {
baseURL, _ := url.Parse(defaultBaseURL)

c := &Client{
httpClient := &httpClient{
baseURL: baseURL,
httpClient: &http.Client{
Timeout: time.Second * 10,
},
}

c := &Client{
http: httpClient,
}
if err := c.applyOptions(opts...); err != nil {
return nil, err
}

c.Users = &UsersService{client: c}
c.Messaging = &MessagingService{client: c}
c.PreferenceCenter = &PreferenceCenterService{client: c}
c.users = &UsersService{
client: c,
}

c.messaging = &MessagingService{
client: c,
}

c.preferenceCenter = &PreferenceCenterService{
client: c,
}

return c, nil
}
Expand All @@ -66,31 +96,31 @@ type ClientOption func(*Client) error
// BaseURL allows to change the default API base url.
func BaseURL(u *url.URL) ClientOption {
return func(c *Client) error {
c.baseURL = u
c.http.baseURL = u
return nil
}
}

// APIKey is a functional option for configuring api access key.
func APIKey(k string) ClientOption {
return func(c *Client) error {
c.apiKey = k
c.http.apiKey = k
return nil
}
}

// UserAgent is a functional option for configuring client user agent.
func UserAgent(a string) ClientOption {
return func(c *Client) error {
c.userAgent = a
c.http.userAgent = a
return nil
}
}

// HTTPClient is a functional option for configuring http client.
func HTTPClient(h *http.Client) ClientOption {
return func(c *Client) error {
c.httpClient = h
c.http.httpClient = h
return nil
}
}
Expand All @@ -104,7 +134,7 @@ func (c *Client) applyOptions(opts ...ClientOption) error {
return nil
}

func (c *Client) newRequest(method string, path string, body interface{}) (*http.Request, error) {
func (c *httpClient) newRequest(method string, path string, body interface{}) (*http.Request, error) {
u := c.baseURL.ResolveReference(&url.URL{Path: path})

var b []byte
Expand All @@ -129,27 +159,13 @@ func (c *Client) newRequest(method string, path string, body interface{}) (*http
return req, nil
}

func (c *Client) do(ctx context.Context, req *http.Request, v interface{}) error {
// TODO remove
// reqDump, err := httputil.DumpRequest(req, true)
// if err != nil {
// panic(err)
// }
// fmt.Printf("%s\n", reqDump)

func (c *httpClient) do(ctx context.Context, req *http.Request, v interface{}) error {
resp, err := c.httpClient.Do(req.WithContext(ctx))
if err != nil {
return err
}
defer resp.Body.Close()

// TODO remove
// respDump, err := httputil.DumpResponse(resp, true)
// if err != nil {
// panic(err)
// }
// fmt.Printf("%s\n", respDump)

if err := parseError(resp); err != nil {
return err
}
Expand Down
8 changes: 4 additions & 4 deletions messaging.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,27 +39,27 @@ type MessagingService struct {
}

func (s *MessagingService) SendMessages(ctx context.Context, r *SendMessagesRequest) (*Response, error) {
req, err := s.client.newRequest(http.MethodPost, messagingMessagesSendPath, r)
req, err := s.client.http.newRequest(http.MethodPost, messagingMessagesSendPath, r)
if err != nil {
return nil, err
}

var res Response
if err := s.client.do(ctx, req, &res); err != nil {
if err := s.client.http.do(ctx, req, &res); err != nil {
return nil, err
}

return &res, nil
}

func (s *MessagingService) TriggerCampaign(ctx context.Context, r *TriggerCampaignRequest) (*Response, error) {
req, err := s.client.newRequest(http.MethodPost, messagingCampaignsTriggerSendPath, r)
req, err := s.client.http.newRequest(http.MethodPost, messagingCampaignsTriggerSendPath, r)
if err != nil {
return nil, err
}

var res Response
if err := s.client.do(ctx, req, &res); err != nil {
if err := s.client.http.do(ctx, req, &res); err != nil {
return nil, err
}

Expand Down
4 changes: 2 additions & 2 deletions preferencecenter.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func (s *PreferenceCenterService) CreateURL(ctx context.Context, r *PreferenceCe

path := fmt.Sprintf("/preference_center/v1/%s/url/%s", r.PreferenceCenterID, r.UserID)

req, err := s.client.newRequest(http.MethodPost, path, r)
req, err := s.client.http.newRequest(http.MethodPost, path, r)
if err != nil {
return nil, err
}
Expand All @@ -56,7 +56,7 @@ func (s *PreferenceCenterService) CreateURL(ctx context.Context, r *PreferenceCe
URL string `json:"preference_center_url"`
}{}

if err := s.client.do(ctx, req, &resp); err != nil {
if err := s.client.http.do(ctx, req, &resp); err != nil {
return nil, err
}

Expand Down
4 changes: 2 additions & 2 deletions preferencecenter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ func TestPreferencesServerCreateURL(t *testing.T) {
client, err := braze.NewClient(braze.APIKey("key"), braze.BaseURL(url))
assert.NoError(t, err)

resp, err := client.PreferenceCenter.CreateURL(context.Background(), &braze.PreferenceCenterCreateURLRequest{
resp, err := client.PreferenceCenter().CreateURL(context.Background(), &braze.PreferenceCenterCreateURLRequest{
PreferenceCenterID: "foo",
UserID: "bar",
})
Expand All @@ -52,7 +52,7 @@ func TestPreferencesServerCreateURLInternalServerError(t *testing.T) {
client, err := braze.NewClient(braze.APIKey("key"), braze.BaseURL(url))
assert.NoError(t, err)

resp, err := client.PreferenceCenter.CreateURL(context.Background(), nil)
resp, err := client.PreferenceCenter().CreateURL(context.Background(), nil)
assert.Error(t, err)
assert.Nil(t, resp)
}
8 changes: 4 additions & 4 deletions users.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,27 +202,27 @@ type UserEvent struct {
type UserPurchase struct{}

func (s *UsersService) Track(ctx context.Context, r *UsersTrackRequest) (*Response, error) {
req, err := s.client.newRequest(http.MethodPost, usersTrackPath, r)
req, err := s.client.http.newRequest(http.MethodPost, usersTrackPath, r)
if err != nil {
return nil, err
}

var res Response
if err := s.client.do(ctx, req, &res); err != nil {
if err := s.client.http.do(ctx, req, &res); err != nil {
return nil, err
}

return &res, nil
}

func (s *UsersService) Delete(ctx context.Context, r *UsersDeleteRequest) (*Response, error) {
req, err := s.client.newRequest(http.MethodPost, usersDeletePath, r)
req, err := s.client.http.newRequest(http.MethodPost, usersDeletePath, r)
if err != nil {
return nil, err
}

var res Response
if err := s.client.do(ctx, req, &res); err != nil {
if err := s.client.http.do(ctx, req, &res); err != nil {
return nil, err
}

Expand Down
6 changes: 3 additions & 3 deletions users_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func TestUsersServiceTrack(t *testing.T) {
}),
)

resp, err := client.Users.Track(context.Background(), &braze.UsersTrackRequest{
resp, err := client.Users().Track(context.Background(), &braze.UsersTrackRequest{
Attributes: []*braze.UserAttributes{
attr,
// This is expected to return a minor error.
Expand Down Expand Up @@ -79,7 +79,7 @@ func TestUsersServiceTrackInternalServerError(t *testing.T) {
client, err := braze.NewClient(braze.APIKey("key"), braze.BaseURL(url))
assert.NoError(t, err)

resp, err := client.Users.Track(context.Background(), nil)
resp, err := client.Users().Track(context.Background(), nil)
assert.Error(t, err)
assert.Nil(t, resp)
}
Expand All @@ -106,7 +106,7 @@ func TestUsersServiceTrackCustomAttributes(t *testing.T) {
}
attr.AddAttributes(braze.BoolAttribute("testing", true))

resp, err := client.Users.Track(context.Background(), &braze.UsersTrackRequest{
resp, err := client.Users().Track(context.Background(), &braze.UsersTrackRequest{
Attributes: []*braze.UserAttributes{attr},
})
assert.NoError(t, err)
Expand Down

0 comments on commit 61e84f8

Please sign in to comment.