Недопустимая ошибка строки JSON в Rails - PullRequest
7 голосов
/ 08 ноября 2010

Я на Rails 2.3.5.В типичном пользовательском контроллере создайте действие

class UsersController
  def create
    @user = User.new(params[:user])
    respond_to do |format]
      if @user.save ...
      else
        format.json ....
      end        
  end
end

Когда клиент передает недопустимую / неправильно сформированную строку JSON для ввода, Rails выдает внутреннюю ошибку 500 сервера, говорящую «Неверная строка JSON».Могу ли я перехватить ошибку, чтобы я мог дать собственное сообщение?

ОБНОВЛЕНО Вот трассировка стека в соответствии с запросом.Просто для ясности, я знаю, что это искаженная строка JSON, мой вопрос не в том, как исправить строку JSON, а в том, как перехватить эту конкретную ошибку, чтобы я мог отправить более значимое сообщение об ошибке, чем внутренняя ошибка сервера HTTP 500,Заранее благодарим за помощь

Error occurred while parsing request parameters.
Contents:

user: {login: "John", email: "john@yahoo.com", password: "111"}}
/!\ FAILSAFE /!\  Mon Nov 08 02:01:04 -0800 2010

  Status: 500 Internal Server Error
  Invalid JSON string
    c:/ruby/lib/ruby/gems/1.8/gems/activesupport-2.3.5/lib/active_support/json/backends/yaml.rb:14:in `decode'
    c:1:in `__send__'
    c:1:in `decode'
    c:/ruby/lib/ruby/gems/1.8/gems/actionpack-2.3.5/lib/action_controller/params_parser.rb:42:in `parse_formatted_parameters'
    c:/ruby/lib/ruby/gems/1.8/gems/actionpack-2.3.5/lib/action_controller/params_parser.rb:11:in `call'
    c:/ruby/lib/ruby/gems/1.8/gems/actionpack-2.3.5/lib/action_controller/session/cookie_store.rb:93:in `call'
    c:/ruby/lib/ruby/gems/1.8/gems/actionpack-2.3.5/lib/action_controller/failsafe.rb:26:in `call'
    c:/ruby/lib/ruby/gems/1.8/gems/rack-1.0.1/lib/rack/lock.rb:11:in `call'
    c:/ruby/lib/ruby/gems/1.8/gems/rack-1.0.1/lib/rack/lock.rb:11:in `synchronize'
    c:/ruby/lib/ruby/gems/1.8/gems/rack-1.0.1/lib/rack/lock.rb:11:in `call'
    c:/ruby/lib/ruby/gems/1.8/gems/actionpack-2.3.5/lib/action_controller/dispatcher.rb:114:in `call'
    c:/ruby/lib/ruby/gems/1.8/gems/actionpack-2.3.5/lib/action_controller/reloader.rb:34:in `run'
    c:/ruby/lib/ruby/gems/1.8/gems/actionpack-2.3.5/lib/action_controller/dispatcher.rb:108:in `call'
    c:/ruby/lib/ruby/gems/1.8/gems/rails-2.3.5/lib/rails/rack/static.rb:31:in `call'
    c:/ruby/lib/ruby/gems/1.8/gems/rack-1.0.1/lib/rack/urlmap.rb:46:in `call'
    c:/ruby/lib/ruby/gems/1.8/gems/rack-1.0.1/lib/rack/urlmap.rb:40:in `each'
    c:/ruby/lib/ruby/gems/1.8/gems/rack-1.0.1/lib/rack/urlmap.rb:40:in `call'
    c:/ruby/lib/ruby/gems/1.8/gems/rails-2.3.5/lib/rails/rack/log_tailer.rb:17:in `call'
    ...
    c:/ruby/lib/ruby/gems/1.8/gems/rack-1.0.1/lib/rack/handler/mongrel.rb:34:in `run'
    c:/ruby/lib/ruby/gems/1.8/gems/rails-2.3.5/lib/commands/server.rb:111
    c:/ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require'
    c:/ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require'
    script/server:3
re.rb:31:in `require'
    script/server:3

Ответы [ 3 ]

6 голосов
/ 14 июня 2011

Я нашел этот плагин для работы с рельсами 3.0.5: https://github.com/kares/request_exception_handler

Как Роб Кэмерон предполагает, что он загружает ваше приложение rails и вызывает parseError из кода вашего приложения. Я не проверял его влияние на производительность, но, похоже, оно работает хорошо.

0 голосов
/ 24 марта 2011

Я сейчас сталкиваюсь с той же проблемой - у меня есть API, которому кто-то может передать недопустимый JSON, и я хочу быть осторожным с ошибкой, которую я возвращаю. Я использую Rails 3.0.5. Я проследил ошибку, выводимую в lib/active_support/json/backends/yaml.rb строку 17:

def decode(json)
  if json.respond_to?(:read)
    json = json.read
  end
  YAML.load(convert_json_to_yaml(json))
rescue ArgumentError
  raise ParseError, "Invalid JSON string"
end

Итак, json.read дает сбой и выдает ошибку. К сожалению, это происходит задолго до того, как ваш контроллер когда-либо вызывается (это часть первоначального разбора параметров запроса, когда Rails связывается с Rack). Я бы подумал, что для того, чтобы поймать это, вам нужно будет добавить немного обезьяньего исправления, чтобы перезаписать некоторые встроенные ошибки и вместо этого всплыть что-то, что вы можете использовать ... возможно, вы могли бы добавить заголовок к объекту запроса что вы можете обнаружить в контроллере и выдать свою собственную ошибку.

К сожалению, я не думаю, что это будет работать для меня, так как я хочу изменить поведение только при доступе к API, а не к остальной части сайта. Хотя я предполагаю, что в monkey-patch, предполагая, что у меня есть доступ к объекту запроса, я мог бы сказать ему, чтобы он использовал мое новое поведение только в том случае, если запрошенный путь соответствует регулярному выражению типа /\/api\//

0 голосов
/ 09 ноября 2010

Если посмотреть в /usr/lib/ruby/gems/1.8/gems/activesupport-2.3.8/lib/active_support/json/backends/yaml.rb (предположительно, немного другой версии), похоже, что ParseError поднял. Предполагая, что ошибка происходит в "format.json", вы можете попробовать что-то вроде

begin
  format.json
rescue ParseError => e
  render :text => "Now there's some ugly JSON! (#{e.message})", :status => 500
end

Если это не сработает, вы можете попытаться поймать его раньше, используя обратный вызов rescue_from в вашем контроллере.

class UsersController < ApplicationController
...
  rescue_from ParseError do |e|
    render ...
  end
...
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...