2012-03-10 9 views
13

A partir de Rails 3.0, de vez en cuando, he estado recibiendo una notificación de excepción de esta manera:suprime ActionView :: excepción MissingTemplate de rieles 3.x

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

Por ejemplo, un escrito a mano arbitraria URL como http://example.com/some/path/robots.txt provoca el error. No es divertido.

Informé del 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

Una solución que se sugiere en esta entrada del blog,

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

Para utilizar esta:

Pero no se siente bien para mí, como yo No estoy interesado en sobrecargar una acción con múltiples formatos. En mi aplicación, hay URL separadas para HTML y JSON API, por lo que el simple render debería ser suficiente.

¿Debo simplemente tragar la excepción por rescue_from ActionView::MissingTemplate y devolver 406 yo?

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

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

Respuesta

5

Si no necesita rutas formateadas, puede deshabilitarlas con: format => false en la especificación de ruta, p. Ej.

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

Esto generará un RoutingError que se convierte en un 404 Not Found. Como alternativa se puede limitar a un número de formatos predefinidos:

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

Si quieres una URL con formato pero que él quiere restringido a un solo formato, entonces usted puede hacer esto:

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

Hay una serie de razones válidas para plantear este error en la producción: un archivo faltante de una implementación, por ejemplo, o tal vez le gustaría notificar a alguien que intenta piratear las URL de su aplicación.

+6

Gracias. Mi conclusión en este punto es que la mayor parte del problema es con ': format'. ¿Hay alguna forma de desactivar ': format' por completo? No quiero agregar ': format => false' a cada definición. – kenn

0

Si hay rutas específicas que periódicamente reciben llamadas que generan errores, y son el mismo conjunto de direcciones URL a las que se llama regularmente (es decir, robots.txt o lo que sea), lo mejor que puede hacer si puede para evitar que golpeen el servidor de sus rieles para comenzar.

Cómo hacer esto depende de su pila de servidores. Una forma de hacerlo es bloquear esto directamente en RACK antes de que la url pase a los rieles.

Otra forma puede ser bloquearlo en NGINX o Unicorn, dependiendo del oyente web que esté utilizando para su aplicación.

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

+0

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 de vez en cuando MUY URLs extrañas recibirán un golpe. SÍ tengo algunas configuraciones de Nginx para calificar el límite o descartar solicitudes no deseadas, pero este ticket no lo es. – kenn

1

Si tienes un recurso que solo se servirá en un formato y quieres ignorar cualquier encabezado de Aceptar y simplemente forzarlo a que muestre siempre el formato por defecto se puede quitar el formato del nombre de archivo de plantilla Así, por ejemplo, si tiene:.

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

puedes cambiarlo simplemente

app/views/some/path/robots.erb 

Algunas escuelas de pensamiento diría que es una Lo malo ya que está devolviendo datos en una forma diferente De lo que se solicitó, sin embargo, en la práctica, hay muchos agentes de usuario que funcionan mal, no todos los sitios filtran cuidadosamente las solicitudes de tipo de contenido, y devolver constantemente lo mismo es un comportamiento predecible, por lo que creo que es un camino razonable.

2

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

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

Trate de añadir

render nothing: true 

al final de su método.

3

Mejor que trabajó para mí está en application_controller.rb:

rescue_from ActionView::MissingTemplate, with: :not_found 
+0

Esto es arriesgado porque no verá un error en la producción si escribe un nombre de plantilla. –