Ответ 1
Вы должны отобразить страницу с правильным статусом.
render(:file => File.join(Rails.root, 'public/403.html'), :status => 403, :layout => false)
У меня есть веб-приложение RoR 3.0, которое выступает в качестве поставщика API OAuth. Теперь в API я бы хотел вернуть правильные коды ошибок HTTP для потребителя API. Как это сделать?
Вот пример:
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
Итак, в случае ошибки я пытаюсь вернуть код Forbidden 403. Тем не менее, при выполнении этого я всегда получаю 404 Not Found. Как вернуть правильный код?
Или это как-то настраиваемая веб-сервер?
Вы должны отобразить страницу с правильным статусом.
render(:file => File.join(Rails.root, 'public/403.html'), :status => 403, :layout => false)
Когда вы просто указываете код состояния и нет тела, удобный способ -
head 403
Этот метод также принимает символические имена для кодов состояния, таких как
head :forbidden
Согласно ActionController:: Head docs, просто используйте этот шаблон в действиях
return head([status]) if/unless [some condition here]
Пример:
return head(:gone) if @record.deleted?
return head(:forbidden) unless @user.owns?(@record)
return
используется, чтобы убедиться, что никакой оставшийся код в действии не будет запущен.
ну, вы можете использовать
:status =>500
Но, по умолчанию Rails позаботится об рендеринге самого типа ошибки.
Ошибки страниц по умолчанию находятся в общем каталоге. 500.html, 404.html и т.д.
Для получения дополнительной информации о :status
, как его использовать, нажмите здесь
Я думаю, у вас есть две проблемы здесь: во-первых, ваша линия @item = Item.find(params[:id])
поднимает 404, а исполнение никогда не доходит до предполагаемого (if
statement). Во-вторых, вы делаете исключения и никогда их не поймаете. Попробуйте:
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
Что-то в этом роде, но вы также упоминали, что вы строите API, поэтому, когда вы спасите ошибку, вы можете отобразить информацию об ошибке xml
. Что-то вроде:
# 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
Удачи. Udachi.