Skip to content

Deprecating API Endpoints

Greggory Rothmeier edited this page Apr 27, 2020 · 2 revisions

As of v3.6.0, Stitches supports deprecating API endpoints using the Sunset: header.

This allows developers to indicate if an endopint is deprecated, when it will be gone, and to then make it explicitly gone.

Suppose you have a kittens-service and its endpoint GET /api/floof_monsters is going to be deprecated on May 4, 2019 (but you still want to keep GET /api/floof_monsters/:id). You'd use deprecated method from Stitches::Deprecation like so:

class Api::V1::FloofMonstersController < ApiController
  # ApiController includes the Stitches::Deprecation module already

  def index
    deprecated gone_on: "2019-05-04" do
      render json: { floof_monsters: [ FloofMonster.all ] }
    end
  end

  def show
    render json: { floof_monster: FloofMonster.find(params[:id]) }
  end
end

This will cause the floof monsters index to behave exactly the same, with two exceptions:

  • The Sunset: HTTP header will be set to the date given to deprecated, in the proper HTTP format
  • An extra log message is emitted about this endpoint being requested. This allows you to search for logs when getting consumers off of your deprecated endpoint

You can assert this is working in an acceptance test:

get "/api/floof_monsters" do
    example "GET all floof monsters" do
      expect(self).to show_deprecation(gone_on: "2019-05-04")

      expect(status).to eq(200)
      # and all other existing expectations about this endpoint's behavior…
    end
end

The show_deprecation expectation will check that the Sunset header is being added, but, more importantly, will fail after the retire date, telling you that you have a deprecated endpoint in production after the advertised retirement date. The endpoint will still work as before (this seems least surprising).

To then retire your endpoint, use gone! from the same Stitches::Deprecation module:

class Api::V1::FloofMonstersController < ApiController

  def index
    gone!
  end

  def show
    render json: { floof_monster: FloofMonster.find(params[:id]) }
  end
end

The have_deprecation matcher will succeed, but of course the rest of your test will fail since the endpoint is now not doing anything. To fix that, replace your test with be_gone:

get "/api/floof_monsters" do
    example "GET all floof monsters" do
      expect(self).to be_gone
      # all other expectations removed
    end
end

The reason to support the endpoint and have it return 410 vs. just removing it and responding with 404 is that if there are any stragglers still using the endpoint after the retirement date, it will be more obvious what is wrong than would be indicated by a 404.

Lastly, this also includes a migration to add the Stitches::Deprecation module to your ApiController if you are already using stitches:

> bin/rails g stitches:add_deprecation
Clone this wiki locally