Stubbing Domain-based APIs

Jun 26, 2017   #docker  #sinatra  #testing  #mock 

In a previous post, I talked about using Docker as a way to stub out calling to external APIs. I showed how I could use my Ruby-based Sinatra-Mock framework to stub out APIs that are port-based. One of the limitations of my framework is that I can only mount to open ports, so I was limited to stubbing port-based APIs.

Since that post, I needed to mock out an API call that was tied to a port 80 HTTP-based API. I want to show how this could also be also be accomplished with Docker and Sinatra-Mock.

If you only need one API, it’s pretty easy:

docker run -p 80:9000 -v $PWD/app.rb:/server/app.rb --name my_website thoom/sinatra-mock

Or with a docker-compose.yml:

  version: "2"
  
  services:
    my_website:
      image: thoom/sinatra-mock
      ports:
        - "80:9000"
      volumes:
        - ./server.rb:/server/app.rb

The format is the same as in the previous post (other than I added a Docker Compose example). Where it gets complicated is when you have to map more than one service to the same port (80 or otherwise). In my case, my dev website is hosted on port 80 through Docker. It needs to communicate with another service that is also mounted on port 80. We must add a proxy that can mount on port 80 (or 443) and route requests between containers.

Fortunately, there are several existing Docker projects that provide this proxy functionality. I use Nginx-Proxy as a proxy for my personal servers. It is a popular, up-to-date Docker project that also integrates easily with Let’s Encrypt (using Let’s Encrypt Proxy Companion).

For this example, I’ll just show how to use port 80. Using HTTPS just requires obtaining SSL certificates for the stubbed URLs. See the Nginx-Proxy documentation for more information on enabling HTTPS.

Updating the original docker-compose file:

 1   version: "2"
 2   
 3   services:
 4     nginx_proxy:
 5       image: jwilder/nginx-proxy
 6       ports:
 7         - "80:80"
 8       volumes:
 9         - /var/run/docker.sock:/tmp/docker.sock:ro
10     my_website:
11       image: thoom/sinatra-mock
12       environment:
13         VIRTUAL_HOST: stubbed-api-example.io
14       volumes:
15         - ./app.rb:/server/app.rb

Lines 4-9: Add the nginx_proxy container and mount it to port 80.
Lines 12-13: Add the VIRTUAL_HOST environment variable for the domain you want the stubbed API to use.

I chose the Nginx-Proxy project because it was simple to implement. In just a handful of lines, it’s now possible to stub out APIs using a domain name instead of port values.