Roteamento e versionamento

· Padrão API
Juan Kalleo
Juan Kalleo
Backend/API
This page hasn't been translated to English yet — showing the original Portuguese content.

Versionado na URL

Toda rota vive sob /api/v1/...config/routes.rb:

namespace :api do
  namespace :v1 do
    namespace :auth do
      get :me, to: "me#show"
      patch :me, to: "me#update"
    end
    get "c_configuracoes/atual", to: "c_configuracoes#atual"
    namespace :admin do
      resources :c_configuracoes
      resources :a_papeis
      # ...
      resources :versions, only: %i[index show]
    end
  end
end

O número na URL (v1) é a estratégia de versionamento inteira — não tem header de versão nem content negotiation por Accept. Simples de propósito: enquanto só existe uma versão, a URL versionada já é suficiente pra abrir caminho pra uma v2 no futuro sem quebrar quem já integra com v1, sem precisar de infraestrutura de negociação que ninguém usa ainda.

admin vs. auth — dois perfis de rota bem separados

namespace :admin agrupa todo CRUD que exige sessão e autorização granular (resources :a_papeis, resources :versions, etc. — um recurso por linha, RESTful puro, sem rota customizada além do que resources já gera). namespace :auth é a exceção: rotas de sessão e perfil próprio (GET/PATCH /api/v1/auth/me), que fazem sentido fora do padrão CRUD porque não são "um recurso entre muitos", são sobre o usuário autenticado em si. O login/logout em si (devise_for :users) fica montado à parte, não dentro de namespace :api — ver Autenticação.

O catch-all tem que ficar dentro do namespace

namespace :api do
  namespace :v1 do
    # ...
  end
  match "*unmatched", to: "/errors#not_found", via: :all
end

Achado real, não teórico: um catch-all (match "*unmatched", ...) puxado pra fora de namespace :api, na raiz do arquivo de rotas, quebrava a resolução de URL do ActiveStorage — rotas do Rails que também vivem na raiz passavam a cair no catch-all antes de chegar na rota real delas. A correção foi simplesmente manter o catch-all como o último item dentro do próprio namespace :api, escopado só ao que já é /api/* — ele nunca compete com rota de fora da API. /errors#not_found devolve o mesmo envelope de erro de qualquer outro 404 (ver Tratamento de erros), então uma URL de API inexistente nunca cai na página de erro HTML padrão do Rails.

Leitura de apoio