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.

On Fluent Interfaces and Go

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.

Dependency Free

You may wonder why we didn’t use a third party Go HTTP client library. Well, there are two main reasons:

  1. The Go native HTTP client is awesome.
  2. 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.

Going Native

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?

Open Source Rest 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.

Design Considerations

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!



Elmer Thomas is SendGrid's Developer Experience Engineer. His mission is to help SendGrid live up to its slogan: "Email Delivery. Simplified" by improving the lives of developers, both internally and externally. Via all sorts of hackery, of course. Follow his exploits on Twitter and GitHub.