2013-02-02 19 views
23

Chciałbym ograniczyć żądania do wszystkich kontrolerów API, aby były przekierowywane do ścieżki JSON. Chciałbym użyć przekierowania, ponieważ adres URL powinien się zmienić zgodnie z odpowiedzią.
Jedną opcją byłoby użycie before_filter, która przekierowuje żądanie do tej samej akcji, ale wymusza format JSON. Przykład nie działa jeszcze!Szyny: Ogranicz żądania API do formatu JSON

# 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 

Inną opcją byłoby ograniczenie formatu w ustawieniach tras.

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

Chcę wszystkim prośba skończyć jako żądanie 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 
... 

Która strategia polecacie?

Odpowiedz

5

Druga opcja, przy użyciu formatu tras. Jeśli użytkownik wyraźnie zażąda formatu XML, nie powinien otrzymać odpowiedzi JSON. Powinien otrzymać wiadomość, że ten adres URL nie odpowiada formatowi XML, lub 404.

Przy okazji, raczej łatwo odpowiedzieć na wszystkie pytania, co należy zrobić w mojej opinii.

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

+1 za początek komentarza. Dodanie formatu nie jest łatwe z mojego doświadczenia, chociaż Railsy ułatwiają implementację. Projektant API wciąż musi przemyśleć, co to znaczy wspierać dodatkowy format, z wszystkimi implikacjami. –

19

Ustawienie domyślnych tras nie spowoduje przekształcenia wszystkich żądań w żądanie JSON.

Co chcesz jest, aby upewnić się, że cokolwiek masz rendering jest odpowiedzią JSON

dość dużo miał go w pierwszej opcji chyba trzeba to zrobić

before_filter :set_default_response_format 

private 
    def set_default_response_format 
    request.format = :json 
    end 

To pójdzie pod swoim podstawowym kontrolerem interfejsu API, aby po jego faktycznym działaniu format zawsze był JSON.

+0

Ustawienie 'request.format' na': json' rozwiązuje problem polegający na tym, że wszystkie odpowiedzi zwracają JSON. Nie zmienia jednak adresu URL na pasku adresu. – JJD

+0

Jeśli używasz interfejsu API, dlaczego musiałbyś wpisać adres URL w pasku adresu? Zauważ, że wykonanie przekierowania przywróci stan 300 i prawdopodobnie nie jest najbardziej efektywny, nie cytuj mnie jednak na ten temat. –

+0

W związku z tym, czy w takim razie zaleca się przepisanie formatu żądania na JSON? Inną opcją byłoby przywrócenie statusu HTTP jako mathieugagne i wspomniałeś. – JJD

16

Jeśli chcesz powrócić 404 lub podnieść RouteNotFound błąd, jeśli format nie jest :json, chciałbym dodać ograniczenie trasy tak:

Wymagaj formatu JSON:

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

Więcej informacji można znaleźć tutaj: http://edgeguides.rubyonrails.org/routing.html#request-based-constraints

+0

Twierdzę, że 406 jest dokładniejszą odpowiedzią w tym przypadku. Każdy pomysł, dlaczego to podejście zwraca 404? – asymmetric