How to return correct HTTP error codes from Ruby o

2019-03-14 08:22发布

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?

5条回答
小情绪 Triste *
2楼-- · 2019-03-14 08:56

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.

查看更多
兄弟一词,经得起流年.
3楼-- · 2019-03-14 08:57

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.

查看更多
干净又极端
4楼-- · 2019-03-14 09:03

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
查看更多
Rolldiameter
5楼-- · 2019-03-14 09:16

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

查看更多
我欲成王,谁敢阻挡
6楼-- · 2019-03-14 09:20

You should render page with correct status.

render(:file => File.join(Rails.root, 'public/403.html'), :status => 403, :layout => false)
查看更多
登录 后发表回答