web-dev-qa-db-ja.com

Ruby on Rails applicationから正しいHTTPエラーコードを返す方法

OAuth APIプロバイダーとして機能しているRoR 3.0 Webアプリケーションがあります。APIでAPIコンシューマーに正しいHTTPエラーコードを返したいのですが、どうすればよいですか?

以下に例を示します。

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が返されます。正しいコードを返すにはどうすればよいですか?

または、これは何らかの形でウェブサーバーの設定可能なものですか?

30
Alexander Savin

ページを正しい状態でレンダリングする必要があります。

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

ステータスコードを与えているだけで、本文がない場合、便利な方法は

head 403

このメソッドは、次のようなステータスコードのシンボル名も受け入れます。

head :forbidden
54

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は、アクション内の残りのコードが実行されないようにするために使用されます。

12
gertas

まあ、使用できます

:status =>500

しかし、デフォルトではRailsはエラータイプのレンダリング自体を処理します。

エラーのデフォルトページはパブリックディレクトリにあります。 500.html、404.htmlなど。

:status、使用方法はここをクリック

1

ここには2つの問題があると思います。1つ目は、@item = Item.find(params[:id])行が404を上げており、実行が意図した場所(ifステートメント)に到達しないことです。 2番目は、例外を発生させて、決してキャッチしないことです。試してください:

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

幸運を。うだち。

1
Simon Bagreev