Supresión de la excepción ActionView :: MissingTemplate para Rails 3.x

Comenzando con Rails 3.0, de vez en cuando, he estado recibiendo una notificación de excepción como esta:

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

Por ejemplo, una URL arbitraria escrita a mano como http://example.com/some/path/robots.txt plantea el error. No es divertido.

Informé el problema en este ticket hace bastante tiempo y he estado usando el parche mencionado aquí, pero el problema persiste.

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

Se sugiere una solución en esta publicación de blog,

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

Para usar esto:

respond_to do |format|
  format.js
end

Pero no me parece bien, ya que no me interesa sobrecargar una acción con múltiples formatos. En mi aplicación, hay URL separadas para HTML y JSON API, tan simple render debería ser suficiente

¿Debería tragarme la excepción por rescue_from ActionView::MissingTemplate y devolver 406 yo mismo?

¿Existe una mejor manera de manejar esta situación?

O puedo preguntar de esta manera: en primer lugar, ¿hay alguna utilidad en el mundo real en plantear este tipo de excepción en la producción?

preguntado el 10 de marzo de 12 a las 02:03

6 Respuestas

Si no necesita rutas formateadas, puede deshabilitarlas con: format => false en la especificación de su ruta, por ejemplo

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

Esto generará un RoutingError que se convierte en un 404 Not Found. Alternativamente, puede restringirlo a varios formatos predefinidos:

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

Si desea una URL formateada pero la desea restringida a un solo formato, puede hacer esto:

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

Hay una serie de razones válidas para generar este error en producción: un archivo faltante de una implementación, por ejemplo, o tal vez desee recibir una notificación de alguien que intenta piratear las URL de su aplicación.

contestado el 13 de mayo de 12 a las 12:05

Gracias. Mi conclusión en este punto es que la mayor parte del problema está en :format. ¿Hay alguna forma de deshabilitar :format ¿enteramente? No quiero agregar :format => false a cada definición. - kenn

@kenn Puede usar el formato: false en la muestra. Pero una mejor opción es usar el formato: 'html' si desea proporcionar un archivo html. scope format: 'html' do # your routes end - criatura del juego

@gamecreature ¡Gracias! Es sorprendente que este tema siga siendo relevante 6 años después. - kenn

Lo mejor que funcionó para mí está en application_controller.rb:

rescue_from ActionView::MissingTemplate, with: :not_found

Respondido el 12 de junio de 16 a las 22:06

Esto es arriesgado porque no verá un error en producción si escribe un nombre de plantilla. - Patrick Brinich Langlois

Después de bucear en una fuente encontré otra manera. Pon esto en un inicializador.

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

contestado el 15 de mayo de 14 a las 21:05

Si tiene un recurso que solo se servirá en un formato y desea ignorar cualquier encabezado de Aceptar y simplemente forzarlo para que siempre muestre el formato predeterminado, puede eliminar el formato del nombre de archivo de la plantilla. Entonces, por ejemplo, si tiene:

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

Puedes cambiarlo a simplemente

app/views/some/path/robots.erb

Algunas escuelas de pensamiento dirían que esto es algo malo, ya que está devolviendo datos en un formato diferente al solicitado, sin embargo, en la práctica hay muchos agentes de usuario que se comportan mal, no todos los sitios filtran cuidadosamente las solicitudes de tipo de contenido y devuelven constantemente el Lo mismo ocurre con el comportamiento predecible, por lo que creo que es una forma razonable de proceder.

Respondido el 02 de junio de 13 a las 12:06

Intenta agregar

render nothing: true

al final de su método.

Respondido el 15 de junio de 15 a las 12:06

Si hay rutas específicas que reciben llamadas periódicamente que generan errores, y son el mismo conjunto de URL que se llaman regularmente (es decir, robots.txt o lo que sea), lo mejor que puede hacer es eliminarlas de golpeando su servidor de rieles para empezar.

Cómo hacer esto depende de la pila de su servidor. Una forma de hacerlo es bloquear esto directamente en RACK antes de que la URL se transfiera a rieles.

Otra forma puede ser bloquearlo en NGINX o Unicorn, dependiendo de qué oyente web esté usando para su aplicación.

Recomendaría investigar esto y luego regresar y publicar una pregunta adicional aquí sobre "¿Cómo bloquear URL usando Rack?" (O unicornio o nginx o donde crea que tenga sentido bloquear el acceso.

contestado el 13 de mayo de 12 a las 13:05

No creo que sea una forma sostenible de manejar este tipo de problemas, porque la naturaleza de este problema no es repetitiva sino aleatoria. Verás que de vez en cuando se acceden a URL MUY extrañas. TENGO algunas configuraciones de Nginx para limitar la tasa o descartar solicitudes no deseadas, pero este boleto no lo es. - kenn

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.