“Client-specific needs”

As the sales team entered the office with a large grin, the dev team began to fear what they see as irrelevant and as a design hell: the infamous “client-specific needs” !

The most feared words across most of dev teams.

This time, a huge prospect likes our product. He likes it so much that he wants to integrate a great part of it to his own ecosystem. Yay!

Unfortunately, our public APIs lack the required endpoints, but our private APIs provide the ones that would allow our prospect to properly integrate our service into their system.

Exposing these APIs was never the plan, and we have to ask ourselves two questions:

How can we continue to make change to these APIs without impacting the client?

How can we spend as little time as possible on developing and providing support for this?

We decided to find a solution to expose only a subset of our API, to ease the integration process of our client.

It came out it was actually possible and quite easy, using AWS API Gateway.

What were our options?

Our first idea was to add another route in our Rails application (we are developers after all, so our initial response to most questions is code!).

After carefully considering all the drawbacks that it would introduce (adherence to the API forbidding to split the service or change the routes at will, the need for a new rate limiting mechanism as our internal APIs does not include one, etc…), we tried to find an alternate solution outside of our Rails application.

We decided to turn to an API management system to gain flexibility, and after considering Kong, and other proprietary solutions, we decided to give a try to AWS API Gateway, which is managed (no need for sys admin work) and really flexible.

What is the API Gateway from AmazonWebServices?

AWS API Gateway allows us to declare an API structure, composed of resources and actions (HTTP verbs) and link them to specific integrations:

AWS Lambda: execute an AWS Lambda function and forward its return

HTTP proxy: forward request to another API

Mock integration: return fake data

AWS service proxy: trigger any action of any AWS service

Using the analogy of Object Oriented Programming, you can look at API Gateway as a factory, a stage as an instance and your resource collection as a class definition.

A stage can be parameterized with throttling, burst limit or specific client certificates for example. This is of paramount importance to us because we have clients with very different needs so being able to fine tune each environment is a must.

Changing an HTTP verb

Assuming you already have an API exposing the following endpoints:

GET: api/v1/clients/{client_id}/apps GET: api/v1/clients/{client_id}/apps/{app_id}/install

You want to:

Avoid exposing to your client the notion of client_id (for security and simplicity).

Configure both your staging and production environments (hence the creation of an URL stage variable).

Transform the second request (install) to a more relevant POST action.

You can create an API Gateway that will follow this setup: