github.com/twilio/twilio-go@v1.20.1/advanced-examples/custom-http-client.md (about)

     1  # Custom HTTP Clients for the Twilio Go Helper Library
     2  
     3  If you are working with the [Twilio Go Helper Library](../README.md), and you need to be able to modify the HTTP requests that the library makes to the Twilio servers, you’re in the right place. The most common reason for altering the HTTP request is to connect and authenticate with an enterprise’s proxy server. We’ll provide sample code that you can drop into your app to handle this use case.
     4  
     5  ## Connect and authenticate with a proxy server
     6  
     7  To connect and provide credentials to a proxy server that may be between your app and Twilio, you need a way to modify the HTTP requests that the Twilio helper library makes on your behalf when invoking Twilio's REST API.
     8  
     9  In Go, the Twilio helper library uses the native [net/http package](https://pkg.go.dev/net/http) under the hood to make the HTTP requests. The Twilio Helper Library allows you to provide your own `Client` for making API requests.
    10  
    11  The following example shows a typical request without a custom `Client`.
    12  
    13  ```go
    14  twilioClient := twilio.NewRestClient()
    15  
    16  params := &twilioApi.CreateMessageParams{}
    17  params.SetTo("+15558675309")
    18  params.SetFrom("+15017250604")
    19  params.SetBody("Hey there!")
    20  
    21  resp, err := twilioClient.Api.CreateMessage(params)
    22  ```
    23  
    24  Out of the box, the helper library creates a default `Client` for you, using the Twilio credentials from your environment variables or that you pass in directly. However, there’s nothing stopping you from creating your own client and using that.
    25  
    26  Once you have your own `Client`, you can pass it to any Twilio REST API resource action you want.
    27  
    28  ## Create and use your custom Client
    29  
    30  When you take a closer look at the input parameters for `twilio.RestClient`, you see that the `Client` parameter is actually of type `client.BaseClient`.
    31  
    32  `client.BaseClient` is an abstraction that allows plugging in any implementation of an HTTP client you want (or even creating a mocking layer for unit testing).
    33  
    34  Now that you understand how all the components fit together, you can create your own `Client` that can connect through a proxy server. To make this reusable, here’s a class that you can use to create this `HttpClient` whenever you need one.
    35  
    36  Here’s an example of sending an SMS message with a custom client:
    37  
    38  ```go
    39  package main
    40  
    41  import (
    42  	"encoding/json"
    43  	"fmt"
    44  	"net/http"
    45  	"os"
    46  
    47  	"github.com/twilio/twilio-go"
    48  	"github.com/twilio/twilio-go/client"
    49  	twilioApi "github.com/twilio/twilio-go/rest/api/v2010"
    50  )
    51  
    52  func main() {
    53  	accountSid := os.Getenv("TWILIO_ACCOUNT_SID")
    54  	authToken := os.Getenv("TWILIO_AUTH_TOKEN")
    55  
    56  	// Add proxy settings to a http Transport object
    57  	transport := &http.Transport{
    58  		// https://pkg.go.dev/net/http#ProxyFromEnvironment
    59  		Proxy: http.ProxyFromEnvironment,
    60  	}
    61  
    62  	// Add the Transport to an http Client
    63  	httpClient := &http.Client{
    64  		Transport: transport,
    65  	}
    66  
    67  	// Create your custom Twilio client using the http client and your credentials
    68  	twilioHttpClient := client.Client{
    69  		Credentials: client.NewCredentials(accountSid, authToken),
    70  		HTTPClient:  httpClient,
    71  	}
    72  	twilioHttpClient.SetAccountSid(accountSid)
    73  	twilioClient := twilio.NewRestClientWithParams(twilio.ClientParams{Client: &twilioHttpClient})
    74  
    75  	params := &twilioApi.CreateMessageParams{}
    76  	params.SetTo("+15558675310")
    77  	params.SetFrom("+15017122661")
    78  	params.SetBody("Hey there!")
    79  
    80  	resp, err := twilioClient.Api.CreateMessage(params)
    81  	if err != nil {
    82  		fmt.Println(err.Error())
    83  	} else {
    84  		response, _ := json.Marshal(*resp)
    85  		fmt.Println("Response: " + string(response))
    86  	}
    87  }
    88  ```
    89  
    90  In this example, you use environment variables loaded at the program startup to retrieve various configuration settings:
    91  
    92  - Your Twilio Account Sid and Auth Token ([found here, in the Twilio console](https://www.twilio.com/console))
    93  - A proxy address in the form of `http://127.0.0.1:8888`
    94  
    95  These settings are either exported manually by yourself in the terminal, or located in a file such as `.env`, like so:
    96  
    97  ```text
    98  ACCOUNT_SID=ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    99  AUTH_TOKEN=your_auth_token
   100  
   101  HTTPS_PROXY=https://127.0.0.1:8888
   102  HTTP_PROXY=http://127.0.0.1:8888
   103  ```
   104  
   105  ## What else can this technique be used for?
   106  
   107  Now that you know how to inject your own `Client` into the Twilio API request pipeline, you could use this technique to add custom HTTP headers and authorization to the requests (perhaps as required by an upstream proxy server). You could do so by overriding the `SendRequest` method, and adding any desired pre-processing to your requests and responses, like so:
   108  
   109  ```go
   110  package main
   111  
   112  import (
   113  	"fmt"
   114  	"net/http"
   115  	"net/url"
   116  	"os"
   117  
   118  	"github.com/twilio/twilio-go"
   119  	"github.com/twilio/twilio-go/client"
   120  	openapi "github.com/twilio/twilio-go/rest/api/v2010"
   121  )
   122  
   123  type MyClient struct {
   124  	client.Client
   125  }
   126  
   127  func (c *MyClient) SendRequest(method string, rawURL string, data url.Values, headers map[string]interface{}) (*http.Response, error) {
   128  	// Custom code to pre-process request here
   129  	resp, err := c.Client.SendRequest(method, rawURL, data, headers)
   130  	// Custom code to pre-process response here
   131  	fmt.Println(resp.StatusCode)
   132  	return resp, err
   133  }
   134  
   135  func main() {
   136  	accountSid := os.Getenv("TWILIO_ACCOUNT_SID")
   137  	authToken := os.Getenv("TWILIO_AUTH_TOKEN")
   138  
   139  	customClient := &MyClient{
   140  		Client: client.Client{
   141  			Credentials: client.NewCredentials(accountSid, authToken),
   142  		},
   143  	}
   144  	customClient.SetAccountSid(accountSid)
   145  
   146  	twilioClient := twilio.NewRestClientWithParams(twilio.ClientParams{Client: customClient})
   147  
   148  	// You may also use custom clients with standalone product services
   149  	twilioApiV2010 := openapi.NewApiServiceWithClient(customClient)
   150  }
   151  ```
   152  
   153  You could also implement your own `Client` to mock the Twilio API responses so your unit and integration tests can run quickly without needing to make a connection to Twilio. In fact, there’s already an example online showing [how to do exactly that with Node.js and Prism](https://www.twilio.com/docs/openapi/mock-api-generation-with-twilio-openapi-spec).
   154  
   155  We can’t wait to see what you build!