web-dev-qa-db-fra.com

Rails: restreindre les demandes d'API au format JSON

Je voudrais limiter les demandes à tous les contrôleurs API pour être redirigées vers le chemin JSON. Je voudrais utiliser une redirection, car l'URL doit également changer en fonction de la réponse.
Une option serait d'utiliser un before_filter qui redirige la demande vers la même action mais force le format JSON. L'exemple ne fonctionne pas encore!

# base_controller.rb
class Api::V1::BaseController < InheritedResources::Base
  before_filter :force_response_format
  respond_to :json
  def force_response_format
    redirect_to, params[:format] = :json
  end
end

Une autre option serait de restreindre le format dans les paramètres des itinéraires.

# routes.rb
MyApp::Application.routes.draw do
  namespace :api, defaults: { format: 'json' } do
    namespace :v1 do
      resources :posts
    end
  end
end

Je veux que toute demande se termine en tant que demande JSON:

http://localhost:3000/api/v1/posts
http://localhost:3000/api/v1/posts.html
http://localhost:3000/api/v1/posts.xml
http://localhost:3000/api/v1/posts.json
...

Quelle stratégie recommanderiez-vous?

25
JJD

La définition d'une valeur par défaut dans vos itinéraires ne transformera pas toutes les demandes en demande JSON.

Ce que vous voulez, c'est vous assurer que tout ce que vous rendez est une réponse JSON

Vous l'aviez à peu près dans la première option, sauf que vous devez le faire

before_filter :set_default_response_format

private
  def set_default_response_format
    request.format = :json
  end

Cela irait sous votre contrôleur API de base de sorte que quand il arrivera à votre action réelle, le format sera toujours JSON.

21
Leo Correa

Si vous souhaitez renvoyer un 404 ou déclencher une erreur RouteNotFound si le format n'est pas :json, J'ajouterais une contrainte d'itinéraire comme ceci:

Exiger le format JSON:

# routes.rb
MyApp::Application.routes.draw do
  namespace :api, constraints: { format: 'json' } do
    namespace :v1 do
      resources :posts
    end
  end
end

Plus d'informations peuvent être trouvées ici: http://edgeguides.rubyonrails.org/routing.html#request-based-constraints

16
PeppyHeppy

Deuxième option, en utilisant le format des routes. Si un utilisateur demande explicitement un format XML, il ne devrait pas recevoir de réponse JSON. Il devrait recevoir un message disant que cette URL ne répond pas au format XML, ou 404.

Soit dit en passant, il serait plutôt facile de répondre à tout ce que vous devriez faire à mon avis.

class FooController
  respond_to :xml, :json
  def show
    @bar = Bar.find(params[:id])
    respond_with(@bar)
  end
end
5
mathieugagne