To prepare for the new
v3/mail/send endpoint, we decided to update our
7 open source client libraries with support for all
v3 Web API calls because the previous versions of the libraries were tightly coupled with the v2 mail send endpoint.
With
Python,
PHP,
C#, and
Ruby, we used reflection and method chaining to implement fluent interfaces, making it easy to build the endpoint URLs.
After consulting with some resident SendGrid Go hackers, and performing some mighty fine Googling, we found that reflection in Go is too expensive right now. So, we decided to forgo the fluent interface.
You may wonder why we didn't use a third party Go HTTP client library. Well, there are two main reasons:
- The Go native HTTP client is awesome.
- We took this opportunity to pare down as many external dependencies as we could across all of our libraries
In the case of the Go client, this was easy since the previous version of the library didn't have any external dependencies.
We want the SendGrid client library to be as lean as possible, and also flexible enough to allow us to build on the lean-core using the concept of
helpers, where the v3/mail/send endpoint became the first available helper.
Since we decided to use Go’s native HTTP client, two questions remain: Why did we make a
new repository for the HTTP client separate from the
SendGrid client, and why didn't we use the
native types included with the Go HTTP client?
Looking further out on the horizon, we decided that we don't want to constrain what HTTP client or JSON parser you use in order to interact with SendGrid. The SendGrid API client should focus on data validation, sensible error handling, and making common use cases easy.
By pulling out the HTTP client, we set the stage for such customizations. Indeed,
that work is on the roadmap currently. Also, we thought it may be useful to the Go community to have a simple HTTP client for any RESTful interface.
Across all the SendGrid client libraries, we decided to standardize the input and output via Request and Response objects. In the case of Go, these objects are represented as structs.
For input, at a minimum, we need the method, URL, request headers, query parameters, and a request body. For output, we need a status code, response body, and response headers. If you look at the
Request and
Response structs provided by the native Go HTTP client, you will find overhead not needed for our simple use case. Instead, we have defined simple
Request and
Response structs.
When we implement the ability to pass-in custom HTTP clients, we just need to make sure we can read/write to those structs.
The next HTTP clients we'll be updating and writing about will be
Java and
Node.js, so check back in the future to read about them!
Happy Hacking!