Подтвердить что ты не робот

Подавление исключения ActionView:: MissingTemplate для Rails 3.x

Начиная с Rails 3.0 время от времени я получаю уведомление об исключении:

ActionView::MissingTemplate: Missing template [...] with {:locale=>[:en],
  :formats=>[:text], :handlers=>[:erb, :builder, :haml]}. Searched in: * [...]

Например, произвольный ручной адрес, например http://example.com/some/path/robots.txt, вызывает ошибку. Не весело.

Я уже давно задал проблему в этом билете и использовал упомянутый здесь патч, но проблема не устранена.

https://rails.lighthouseapp.com/projects/8994/tickets/6022-content-negotiation-fails-for-some-headers-regression

В этом сообщении в блоге предлагается исправление,

http://trevorturk.wordpress.com/2011/12/09/handling-actionviewmissingtemplate-exceptions/

Чтобы использовать это:

respond_to do |format|
  format.js
end

Но мне это не кажется правильным, поскольку мне не интересно перегружать действие несколькими форматами. В моем приложении есть отдельные URL-адреса для HTML и JSON API, поэтому достаточно простого render.

Должен ли я просто проглатывать исключение с помощью rescue_from ActionView::MissingTemplate и возвращать 406 себя?

Есть ли лучший способ справиться с этой ситуацией?

Или я могу спросить этот путь - во-первых, есть ли какая-либо реальная полезность в создании такого исключения при производстве?

4b9b3361

Ответ 1

Если вам нет необходимости в форматированных маршрутах, вы можете отключить их: format = > false в спецификации маршрута, например

get '/products' => 'products#index', :format => false

Это создаст RoutingError, который преобразуется в 404 Not Found. В качестве альтернативы вы можете ограничить его несколькими предопределенными форматами:

get '/products' => 'products#index', :format => /(?:|html|json)/

Если вы хотите отформатированный URL-адрес, но хотите, чтобы он был ограничен одним форматом, вы можете сделать это:

get '/products.json' => 'products#index', :format => false, :defaults => { :format => 'json' }

Существует ряд веских причин для повышения этой ошибки в производстве - например, отсутствующий файл из развертывания или, возможно, вам нужно получить уведомление о том, что кто-то пытается взломать ваши URL-адреса приложения.

Ответ 2

Лучшее, что сработало для меня, находится в application_controller.rb:

rescue_from ActionView::MissingTemplate, with: :not_found

Ответ 3

После некоторого подводного погружения я нашел другой путь. Поместите это в инициализатор.

ActionDispatch::ExceptionWrapper.rescue_responses.merge! 'ActionView::MissingTemplate' => :not_found

Ответ 4

Если у вас есть ресурс, который будет использоваться только в одном формате, и вы хотите игнорировать любой заголовок Accept и просто заставить его всегда выводить формат по умолчанию, вы можете удалить формат из имени файла шаблона. Например, если у вас есть:

app/views/some/path/robots.txt.erb

Вы можете изменить его просто

app/views/some/path/robots.erb

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

Ответ 5

Попробуйте добавить

render nothing: true

в конце вашего метода.

Ответ 6

Если есть определенные пути, которые периодически вызываются, которые генерируют ошибки, - и они представляют собой тот же набор URL-адресов, которые регулярно вызываются (например, robots.txt или что-то еще) - лучше всего сделать, если вы можете это сделать устраните их от попадания на сервер рельсов, чтобы начать с.

Как это сделать, зависит от вашего стека серверов. Один из способов сделать это - заблокировать это непосредственно в RACK до того, как URL будет передан в рельсы.

Другой способ - заблокировать его в NGINX или Unicorn, в зависимости от того, какой веб-прослушиватель вы используете для своего приложения.

Я бы порекомендовал изучить это, а затем вернуться и опубликовать дополнительный вопрос здесь: "Как заблокировать URL-адрес с помощью Rack?" (или unicorn или nginx, или где бы вы ни думали, что имеет смысл блокировать доступ.