Изменить код ответа HTTP с помощью Rails и RABL

Я использую RABL для своего REST API. Однако в настоящее время, даже если есть ошибка, код ответа HTTP, который я получаю, равен 200. Есть ли способ изменить его на код уровня 4xx? Было бы здорово, если бы мой клиент прочитал.

Я не использую render template: "api/v1/error.rabl”, потому что, если я его использую, есть фильтр after, который устанавливает заголовки управления доступом CORS, которые не выполняются.

Я пытался искать, но не нашел способа.


person Rahul Jiresal    schedule 15.12.2013    source источник
comment
так что же вы используете для вызова рендеринга?   -  person phoet    schedule 16.12.2013
comment
Я позволяю методу контроллера возвращаться естественным образом, поэтому файл RABL автоматически вызывается Rails как представление.   -  person Rahul Jiresal    schedule 16.12.2013
comment
чем это отличается от вызова рендеринга самостоятельно?   -  person phoet    schedule 16.12.2013


Ответы (1)


Похоже, этот ответ предлагает хорошее решение. Например,

class FoosController < ActionController::Base
  respond_to :json

  class ApiResponder < ActionController::Responder
    def to_format
      case
      when has_errors?
        controller.response.status = :unprocessable_entity
      when get? && !resource
        controller.response.status = :not_found
      when post?
        controller.response.status = :created
      end

      default_render
    rescue ActionView::MissingTemplate => e
      api_behavior(e)
    end
  end
  self.responder = ApiResponder

  def show
    @foo = Foo.find(params[:id])
    @foo.errors.add(:base, "foo bar") # e.g. of errors on the object
    respond_with @foo
  end
end

Хотя на вики есть предупреждение о том, что "настройка controller.response.status похожа на значение по умолчанию" , respond_with или render не должны явно устанавливать status, и похоже, что вызов render "my_template" вызывает 200, о котором вы упомянули. Если вы хотите повторно использовать один шаблон ошибки, что-то вроде предложенного автором шаблона, это работает:

  ...

  self.responder = ApiResponder

  def show
    @foo = Foo.find(params[:id])
    @foo.errors.add(:base, "foo bar") # e.g. of errors on the object
    respond_with @foo do |format|
      if @foo.errors.empty?
        flash[:notice] = 'Foo was successfully created.'
      else
        format.json { render "error" }
      end
    end
  end

# error.rabl
object false

node :errors do
  {
    :message => "Sorry, fubar'ed",
    :code => 12345
  }
end

Это работает с действиями, которые записывают и читают. В обсуждении исходной ошибки также есть несколько интересных примеров.

person phillbaker    schedule 14.01.2014