estoy teniendo una interfaz HTML normal y una API JSON en mi aplicación Rails. Ahora, si alguien llama al /api/not_existent_method.json
, devuelve la página HTML 404 predeterminada. ¿Hay alguna manera de cambiar esto a algo como {"error": "not_found"}
dejando intacta la página 404 original para la interfaz HTML?necesidad de volver de error en formato JSON, 404 en los carriles
Respuesta
Un amigo me señaló hacia una solución elegante que no sólo manejar 404 500 sino también errores. De hecho, maneja todos los errores. La clave es que cada error genera una excepción que se propaga hacia arriba a través de la pila de middlewares de rack hasta que es manejado por uno de ellos. Si está interesado en obtener más información, puede ver this excellent screencast. Rails tiene sus propios controladores para las excepciones, pero puede anularlos mediante la opción de configuración exceptions_app
menos documentada. Ahora, usted puede escribir su propio middleware o puede enrutar el error de nuevo en los carriles, así:
# In your config/application.rb
config.exceptions_app = self.routes
A continuación, sólo tiene que relacionar estas rutas en su config/routes.rb
:
get "/404" => "errors#not_found"
get "/500" => "errors#exception"
Y entonces solo crea un controlador para manejar esto.
class ErrorsController < ActionController::Base
def not_found
if env["REQUEST_PATH"] =~ /^\/api/
render :json => {:error => "not-found"}.to_json, :status => 404
else
render :text => "404 Not found", :status => 404 # You can render your own template here
end
end
def exception
if env["REQUEST_PATH"] =~ /^\/api/
render :json => {:error => "internal-server-error"}.to_json, :status => 500
else
render :text => "500 Internal Server Error", :status => 500 # You can render your own template here
end
end
end
Una última cosa que añadir: En el entorno de desarrollo, los carriles Normalamente no hace que las páginas 404 o 500, pero imprime una traza en su lugar. Si quiere ver su ErrorsController
en acción en modo de desarrollo, deshabilite el material de rastreo en su archivo config/enviroments/development.rb
.
config.consider_all_requests_local = false
Claro, que se verá algo como esto:
class ApplicationController < ActionController::Base
rescue_from NotFoundException, :with => :not_found
...
def not_found
respond_to do |format|
format.html { render :file => File.join(Rails.root, 'public', '404.html') }
format.json { render :text => '{"error": "not_found"}' }
end
end
end
NotFoundException
es no el nombre real de la excepción. Variará con la versión de Rails y el comportamiento exacto que desee. Bastante fácil de encontrar con una búsqueda en Google.
Gracias por la idea, pero Estoy usando Rails 3.2.2 donde cambió el manejo de excepciones. Esto ya no funcionará. – iblue
@iblue Esto funciona bien en Rails 3.2+ y es la mejor solución. Consulte 'rescue_from' [docs] (http://apidock.com/rails/v3.2.3/ActiveSupport/Rescuable/ClassMethods/rescue_from) para obtener más información. – Intelekshual
Funciona solo para errores 404, no para 500 errores. – iblue
tratar de poner al final de suroutes.rb
:
match '*foo', :format => true, :constraints => {:format => :json}, :to => lambda {|env| [404, {}, ['{"error": "not_found"}']] }
Para cualquier otra persona que lea esto, 'match' en el archivo' Rails.application.routes' ahora requiere que especifique el método HTTP, a través del parámetro 'via:'. Esto también aparecerá como un error cuando intente utilizar la línea anterior. – sameers
me gusta crear un controlador de API que establece el formato JSON() y los métodos específicos de la API:
class ApiController < ApplicationController
respond_to :json
rescue_from ActiveRecord::RecordNotFound, with: :not_found
# Use Mongoid::Errors::DocumentNotFound with mongoid
def not_found
respond_with '{"error": "not_found"}', status: :not_found
end
end
RSpec prueba:
it 'should return 404' do
get "/api/route/specific/to/your/app/", format: :json
expect(response.status).to eq(404)
end
Esto parece funcionar solo para registros. ¿Cómo manejarías el caso de 'api/non_existant_route'? – Sebastialonso
la línea 'rescue_from ActiveRecord :: RecordNotFound, with: not_found' debe ser' with:: not_found' pero solo es una edición de un carácter: P – erroric
@erroric gracias! :) –
- 1. validaciones de formato múltiple en los carriles
- 2. de anidamiento: JSON incluir en los carriles
- 3. carriles 3 muestran 404
- 4. : formato en el link_to no funciona en los carriles 3.2.2
- 5. Error personalizado de Django 404
- 6. volver cada fila n de la base de datos utilizando ActiveRecord en los carriles
- 7. ¿Cómo obtener los datos mostrados de KendoGrid en formato json?
- 8. Los archivos .axd generan un error 404
- 9. datos POST en formato JSON
- 10. Rescate de los carriles de error de enrutamiento 3.1
- 11. rubí en los carriles rastrillo db: migrate error
- 12. carriles de error de sintaxis delgada
- 13. error 404 con ClientBin
- 14. f.hidden_field en los carriles de 3,2
- 15. En Kohana, ¿puede desencadenar un error 404?
- 16. Cómo atrapar el error 404 en urllib.urlretrieve
- 17. conexión de base múltiple en los carriles
- 18. Apache Tomcat 404 Error
- 19. OpenRDF Sesame - error 404
- 20. error 404 en la configuración personalizada de Magento en admin
- 21. Volver JSON desde el controlador MVC pero Formato fecha no adecuada en javascript
- 22. Error 404 FavIco del bloque en ELMAh
- 23. ¿Para qué sirven los códigos de error HTTP 404, 1, 404, 2, etc.?
- 24. node.js + connect error 404
- 25. Asociación privada en los carriles
- 26. default_scope en los carriles 3
- 27. enormes migraciones de datos en los carriles
- 28. de nomenclatura columnas booleanas en los carriles
- 29. Ruta de análisis en los carriles
- 30. modelos de actualización en los carriles/migraciones
Además, no olvide agregar el código de estado a los renders. De lo contrario, su cliente/navegador no sabrá que era un 404/500. render: text => "404 Not Found",: estado =>: not_found – arnab
he editado mi respuesta. – iblue
Diría que un bloque de respuesta es más universal en las funciones de representación: responde_to do | format | format.json {render json: {error: "no encontrado"}. To_json, estado: 404} format.html {render text: "404 No encontrado", estado: 404} final –