Skip to content

Commit

Permalink
Revert "feat: introduce base client that utilizes context (#196)"
Browse files Browse the repository at this point in the history
This reverts commit b61e334.
  • Loading branch information
Sam Harrison committed Nov 9, 2022
1 parent e89399c commit 79f196e
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 170 deletions.
35 changes: 0 additions & 35 deletions client/base_client.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package client

import (
"context"
"net/http"
"net/url"
"time"
Expand All @@ -13,37 +12,3 @@ type BaseClient interface {
SendRequest(method string, rawURL string, data url.Values,
headers map[string]interface{}) (*http.Response, error)
}

// BaseClientWithCtx is an extension of BaseClient with the ability to associate a contex with
// the request
type BaseClientWithCtx interface {
BaseClient
SendRequestWithCtx(ctx context.Context, method string, rawURL string, data url.Values,
headers map[string]interface{}) (*http.Response, error)
}

// wrapperClient wraps the lower level BaseClient to fulfill the BaseClientWithCtx interface. This
// allows the SDK to utilize the BaseClientWithCtx method throughout the codebase.
//
// All *WithCtx methods of a wrapped client will not actually use their context.Context argument.
type wrapperClient struct {
// embed the BaseClient so the functions remain accessible
BaseClient
}

// SendRequestWithCtx passes the request through to the underlying BaseClient. The context.Context
// argument is not utilized.
func (w wrapperClient) SendRequestWithCtx(ctx context.Context, method string, rawURL string, data url.Values,
headers map[string]interface{}) (*http.Response, error) {
return w.SendRequest(method, rawURL, data, headers)
}

// wrapBaseClientWithNoopCtx "upgrades" a BaseClient to BaseClientWithCtx so that requests can be
// send with a request context.
func wrapBaseClientWithNoopCtx(c BaseClient) BaseClientWithCtx {
// the default library client has SendRequestWithCtx, use it if available.
if typedClient, ok := c.(BaseClientWithCtx); ok {
return typedClient
}
return wrapperClient{BaseClient: c}
}
11 changes: 2 additions & 9 deletions client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
package client

import (
"context"
"encoding/json"
"fmt"
"net/http"
Expand Down Expand Up @@ -45,7 +44,7 @@ func defaultHTTPClient() *http.Client {
}
}

func (c *Client) basicAuth() (username, password string) {
func (c *Client) basicAuth() (string, string) {
return c.Credentials.Username, c.Credentials.Password
}

Expand Down Expand Up @@ -90,12 +89,6 @@ func (c *Client) doWithErr(req *http.Request) (*http.Response, error) {

// SendRequest verifies, constructs, and authorizes an HTTP request.
func (c *Client) SendRequest(method string, rawURL string, data url.Values,
headers map[string]interface{}) (*http.Response, error) {
return c.SendRequestWithCtx(context.TODO(), method, rawURL, data, headers)
}

// SendRequestWithCtx verifies, constructs, and authorizes an HTTP request.
func (c *Client) SendRequestWithCtx(ctx context.Context, method string, rawURL string, data url.Values,
headers map[string]interface{}) (*http.Response, error) {
u, err := url.Parse(rawURL)
if err != nil {
Expand All @@ -119,7 +112,7 @@ func (c *Client) SendRequestWithCtx(ctx context.Context, method string, rawURL s
valueReader = strings.NewReader(data.Encode())
}

req, err := http.NewRequestWithContext(ctx, method, u.String(), valueReader)
req, err := http.NewRequest(method, u.String(), valueReader)
if err != nil {
return nil, err
}
Expand Down
28 changes: 0 additions & 28 deletions client/client_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package client_test

import (
"context"
"encoding/json"
"io"
"net/http"
Expand Down Expand Up @@ -211,33 +210,6 @@ func TestClient_SetTimeoutTimesOut(t *testing.T) {
assert.Error(t, err)
}

func TestClient_SetTimeoutTimesOutViaContext(t *testing.T) {
handlerDelay := 100 * time.Microsecond
clientTimeout := 10 * time.Microsecond
assert.True(t, clientTimeout < handlerDelay)

timeoutServer := httptest.NewServer(http.HandlerFunc(
func(writer http.ResponseWriter, _ *http.Request) {
d := map[string]interface{}{
"response": "ok",
}
time.Sleep(100 * time.Microsecond)
encoder := json.NewEncoder(writer)
err := encoder.Encode(&d)
if err != nil {
t.Error(err)
}
writer.WriteHeader(http.StatusOK)
}))
defer timeoutServer.Close()

c := NewClient("user", "pass")
ctx, cancel := context.WithTimeout(context.TODO(), 10*time.Microsecond)
defer cancel()
_, err := c.SendRequestWithCtx(ctx, "GET", timeoutServer.URL, nil, nil) //nolint:bodyclose
assert.Error(t, err)
}

func TestClient_SetTimeoutSucceeds(t *testing.T) {
timeoutServer := httptest.NewServer(http.HandlerFunc(
func(writer http.ResponseWriter, request *http.Request) {
Expand Down
10 changes: 0 additions & 10 deletions client/page_util.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package client

import (
"context"
"encoding/json"
"fmt"
"strings"
Expand Down Expand Up @@ -35,15 +34,6 @@ func GetNext(baseUrl string, response interface{}, getNextPage func(nextPageUri
return getNextPage(nextPageUrl)
}

func GetNextWithCtx(ctx context.Context, baseUrl string, response interface{}, getNextPage func(ctx context.Context, nextPageUri string) (interface{}, error)) (interface{}, error) {
nextPageUrl, err := getNextPageUrl(baseUrl, response)
if err != nil {
return nil, err
}

return getNextPage(ctx, nextPageUrl)
}

func toMap(s interface{}) (map[string]interface{}, error) {
var payload map[string]interface{}
data, err := json.Marshal(s)
Expand Down
118 changes: 30 additions & 88 deletions client/request_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,38 @@
package client

import (
"context"
"net/http"
"net/url"
"os"
"strings"
)

func buildUrlInternal(overrideEdge, overrideRegion, rawURL string) (string, error) {
type RequestHandler struct {
Client BaseClient
Edge string
Region string
}

func NewRequestHandler(client BaseClient) *RequestHandler {
return &RequestHandler{
Client: client,
Edge: os.Getenv("TWILIO_EDGE"),
Region: os.Getenv("TWILIO_REGION"),
}
}

func (c *RequestHandler) sendRequest(method string, rawURL string, data url.Values,
headers map[string]interface{}) (*http.Response, error) {
parsedURL, err := c.BuildUrl(rawURL)
if err != nil {
return nil, err
}

return c.Client.SendRequest(method, parsedURL, data, headers)
}

// BuildUrl builds the target host string taking into account region and edge configurations.
func (c *RequestHandler) BuildUrl(rawURL string) (string, error) {
u, err := url.Parse(rawURL)
if err != nil {
return "", err
Expand Down Expand Up @@ -39,12 +63,12 @@ func buildUrlInternal(overrideEdge, overrideRegion, rawURL string) (string, erro
region = pieces[2]
}

if overrideEdge != "" {
edge = overrideEdge
if c.Edge != "" {
edge = c.Edge
}

if overrideRegion != "" {
region = overrideRegion
if c.Region != "" {
region = c.Region
} else if region == "" && edge != "" {
region = "us1"
}
Expand All @@ -59,96 +83,14 @@ func buildUrlInternal(overrideEdge, overrideRegion, rawURL string) (string, erro
return u.String(), nil
}

type RequestHandler struct {
Client BaseClient
Edge string
Region string
}

func NewRequestHandler(client BaseClient) *RequestHandler {
return &RequestHandler{
Client: client,
Edge: os.Getenv("TWILIO_EDGE"),
Region: os.Getenv("TWILIO_REGION"),
}
}

func (c *RequestHandler) sendRequest(method string, rawURL string, data url.Values,
headers map[string]interface{}) (*http.Response, error) {
parsedURL, err := c.BuildUrl(rawURL)
if err != nil {
return nil, err
}

return c.Client.SendRequest(method, parsedURL, data, headers)
}

// BuildUrl builds the target host string taking into account region and edge configurations.
func (c *RequestHandler) BuildUrl(rawURL string) (string, error) {
return buildUrlInternal(c.Edge, c.Region, rawURL)
}

// deprecated
func (c *RequestHandler) Post(path string, bodyData url.Values, headers map[string]interface{}) (*http.Response, error) {
return c.sendRequest(http.MethodPost, path, bodyData, headers)
}

// deprecated
func (c *RequestHandler) Get(path string, queryData url.Values, headers map[string]interface{}) (*http.Response, error) {
return c.sendRequest(http.MethodGet, path, queryData, headers)
}

// deprecated
func (c *RequestHandler) Delete(path string, nothing url.Values, headers map[string]interface{}) (*http.Response, error) {
return c.sendRequest(http.MethodDelete, path, nil, headers)
}

func UpgradeRequestHandler(h *RequestHandler) *RequestHandlerWithCtx {
return &RequestHandlerWithCtx{
// wrapped client will supply context.TODO() to all API calls
Client: wrapBaseClientWithNoopCtx(h.Client),
Edge: h.Edge,
Region: h.Region,
}
}

type RequestHandlerWithCtx struct {
Client BaseClientWithCtx
Edge string
Region string
}

func (c *RequestHandlerWithCtx) sendRequest(ctx context.Context, method string, rawURL string, data url.Values,
headers map[string]interface{}) (*http.Response, error) {
parsedURL, err := c.BuildUrl(rawURL)
if err != nil {
return nil, err
}

return c.Client.SendRequestWithCtx(ctx, method, parsedURL, data, headers)
}

func NewRequestHandlerWithCtx(client BaseClientWithCtx) *RequestHandlerWithCtx {
return &RequestHandlerWithCtx{
Client: client,
Edge: os.Getenv("TWILIO_EDGE"),
Region: os.Getenv("TWILIO_REGION"),
}
}

// BuildUrl builds the target host string taking into account region and edge configurations.
func (c *RequestHandlerWithCtx) BuildUrl(rawURL string) (string, error) {
return buildUrlInternal(c.Edge, c.Region, rawURL)
}

func (c *RequestHandlerWithCtx) Post(ctx context.Context, path string, bodyData url.Values, headers map[string]interface{}) (*http.Response, error) {
return c.sendRequest(ctx, http.MethodPost, path, bodyData, headers)
}

func (c *RequestHandlerWithCtx) Get(ctx context.Context, path string, queryData url.Values, headers map[string]interface{}) (*http.Response, error) {
return c.sendRequest(ctx, http.MethodGet, path, queryData, headers)
}

func (c *RequestHandlerWithCtx) Delete(ctx context.Context, path string, nothing url.Values, headers map[string]interface{}) (*http.Response, error) {
return c.sendRequest(ctx, http.MethodDelete, path, nil, headers)
}

0 comments on commit 79f196e

Please sign in to comment.