2012-02-03 13 views
25

Mam aplikację internetową RoR 3.0, która działa jako dostawca OAuth API. Teraz w API chciałbym zwrócić prawidłowe kody błędów HTTP do konsumenta API. Jak mam to zrobic?Jak zwracać poprawne kody błędów HTTP z aplikacji Ruby on Rails

Oto przykład:

def destroy_oauth 
    @item = Item.find(params[:id]) 
    if([email protected]? && @item.user_id == current_user.id) 
     @item.destroy 
     respond_to do |format| 
       format.js 
       format.xml 
     end 
    else 
     raise ActionController::RoutingError.new('Forbidden') 
    end 
end 

Tak więc, w przypadku błędu próbuję powrócić Zakazane kod 403. Mimo to, podczas uruchamiania tego, zawsze otrzymuję zwrot 404 Not Found. Jak mogę zwrócić prawidłowy kod?

Czy to w jakiś sposób konfigurowalne oprogramowanie serwera WWW?

Odpowiedz

31

Powinieneś renderować stronę z prawidłowym stanem.

render(:file => File.join(Rails.root, 'public/403.html'), :status => 403, :layout => false) 
+0

Czy powinienem to zrobić również w przypadku odpowiedzi XML xml OAuth? –

+2

Jako komentarz boczny, określenie tego rozszerzenia '.html' jest przestarzałe (patrz dyskusja na https://github.com/rails/rails/issues/7288), więc powinniśmy użyć' render (: file = > File.join (Rails.root, 'public/403'),: formats => [: html],: status => 403,: layout => false) '(zwróć uwagę na sposób, w jaki określiłem format). –

+0

... lub nawet "render (: file => Rails.root.join (" public "," 403 "),: formats => [: html],: status => 403,: layout => false) . –

1

dobrze można użyć

:status =>500 

Ale zalega Szyny dbać o rodzaju błędu się renderingu.

Błędy domyślne strony znajdują się w katalogu publicznym. 500.html, 404.html etc ..

For more information on :status , how to use it click here

+1

Tak, prawdopodobnie muszę grać z tymi parametrami: status. Dzięki! –

+0

To prawda. Jeśli jednak pracuję nad interfejsem API w szynach, powinienem wyraźnie podać kod statusu: – Kiong

42

Po prostu podając kod stanu i nie ma ciała, wygodnym sposobem jest

head 403 

Metoda ta przyjmuje również symboliczne nazwy dla kodów statusu, takiej jak

head :forbidden 
+0

Och, to może być to, czego potrzebuję. Spróbuję. –

1

myślę, że masz dwa problemy: po pierwsze jest to, że linia @item = Item.find(params[:id]) jest podnoszenie 404 i wykonanie nigdy nie trafia do gdzi e przeznaczone (oświadczenie if). Po drugie, podnosisz wyjątki i nigdy ich nie łapiesz. Spróbuj:

def destroy_oauth 
    begin 
    @item = Item.find(params[:id]) 
    if([email protected]? && @item.user_id == current_user.id) 
     @item.destroy 
     respond_to do |format| 
      format.js 
      format.xml 
     end 
    else 
     raise ActionController::RoutingError.new('Forbidden') 
    end 
    rescue ActiveRecord::ResourceNotFound 
    redirect_to :action => 'not_found', :status => 404 # do whatever you want here 
    rescue ActionController::RoutingError 
    redirect_to :action => 'forbidden', :status => 403 # do whatever you want here 
    end 
end 

coś wzdłuż tych linii, ale również wspomnieć, że budujesz API, więc podczas ratowania błąd, może chcesz uczynić xml informacje o błędzie. Coś jak:

# in application_controller.rb 
rescue_from ActionController::RoutingError, :with => :render_forbidden_error 

private 

def render_forbidden_error(e) 
    render :status => e.status, :xml => e 
end 

Powodzenia. Udachi.

10

Według ActionController::Head docs prostu użyć tego wzoru w działaniach

return head([status]) if/unless [some condition here] 

Przykład:

return head(:gone) if @record.deleted? 
    return head(:forbidden) unless @user.owns?(@record) 

return stosowany jest, aby upewnić się, że będzie prowadzony nie pozostały kod w akcji.