I have RoR 3.0 web application which is acting as an OAuth API provider. Now, in API I'd like to return correct HTTP error codes to the API consumer. How do I do this?
Here is example:
def destroy_oauth
@item = Item.find(params[:id])
if(!@item.nil? && @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
So, in case of error I'm trying to return Forbidden 403 code. Still, when running this I'm getting always 404 Not Found returned. How do I return the correct code?
Or is this somehow webserver configurable thing?
You should render page with correct status.
render(:file => File.join(Rails.root, 'public/403.html'), :status => 403, :layout => false)
When you're just giving a status code and there is no body, a convenient way is
head 403
This method also accepts the symbolic names for status codes, such as
head :forbidden
According to ActionController::Head docs just use this pattern in actions
return head([status]) if/unless [some condition here]
Example:
return head(:gone) if @record.deleted?
return head(:forbidden) unless @user.owns?(@record)
return
is used to make sure that no remaining code in the action will be run.
well, you can use
:status =>500
But, In default Rails take care of the error type rendering itself.
Errors default pages are in the public directory. 500.html,404.html etc..
For more information on :status
, how to use it click here
I think you have two problems here: first is that your @item = Item.find(params[:id])
line is raising 404 and execution never gets to where intended (if
statement). Second is that you are raising exceptions and never catch them. Try:
def destroy_oauth
begin
@item = Item.find(params[:id])
if(!@item.nil? && @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
Something along those lines, but you also mentioned that you are building the API, so when you are rescuing the error, you may want to render xml
error info. Something like:
# 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
Good luck. Udachi.