1 min read

Selective Proxies

I wanted to test a service following "mock almost nothing" principles with a fully-wired application stack but one of the services connected to a real API endpoint. This is all well and good, but the external API limits the number calls that can be made and running the auto-tests will smash through that limit in short order.

I can easily drop a stub for the external API into the environments but sometimes, especially for end-to-end testing, I actually want to use the real service and want to avoid having to to redploy the entire stack if I can avoid it.

I found the excellent Roda framework which makes knocking up APIs a cinch. Building a quick reverse proxy gem was stupidly quick and easy. With this, I can stub the external and sometimes proxy out to the real thing.

Let's say I want alway want to proxy a GET request to my/api, here's how I could do it...

require 'roda'
require 'roda/proxy'

class App < Roda
  plugin :proxy, 
         to: 'https://my.server.com', 
         path_prefix: '/my/api'
         
  route do |r|
  # /my
  r.on 'my' do
    # /my/api
    r.on 'api' do
      # GET /my/api/path
      r.get do
        r.proxy
      end
    end
  end
end

And that's it. But since I've also got access to the request, headers and all, I can exploit that with another method the gem provides. Here, I'll proxy the request if a Proxy-Me header is sent in the request...

r.proxy_when(r.env['PROXY-ME'] == 'true') do
  # This request has not been proxied
  response['Content-Type'] = 'application/json'
  {hello: 'world').to_json
end

The proxy_when method will proxy when it's passed true, otherwise it'll execute it's code block like a normal bit of Roda.

I can even through a dice and proxy 50% of the time, even when proxying is enabled...

r.proxy_when(r.env['PROXY-ME'] == 'true', probability: 0.5) do
  # maybe I'll proxy, maybe I won't
end

This way I can make sure I'm still getting some contact with the real endpoint but still limit the amount of traffic hitting the real service.