Closed jonathanphilippou closed 6 years ago
Can you share your repository?
In terms of the 404 error page, I think it's because you may have your /public/404.html
page still intact. If you remove that, it should work.
Rich
Hey @richpeck
I can't share the repo bc it's for work, but I tried removing /public/404.html
and it worked!
However, I still get the 500 page i showed above. I tried deleting the /public/500.html
. What else do you think needs to be done?
That error you're seeing is basically the "failsafe" for Rails, meaning that it hit a 500 error, tried to show the "exception" page (provided by ExceptionHandler
) and it failed again.
The issue is typically because you're trying to use exactly the same layout as your main app / 404 errors page (hence it will be using something like the same variables or similar). If this is the case, you need to limit any db calls when using the 500 error layout.
Hi, I have also something similar, maybe someone can help me. ruby "2.3.3" gem 'rails', '~> 5.0.6' gem 'exception_handler', '~>0.7.7.0'
I add also config.exception_handler at development.rb
:
config.exception_handler = {
dev: true,
layouts: {
'404' => 'exception',
'500' => 'exception'
},
}
When I force a 500 error (raise ....
), than I see the new error page, but why when I call just /404 I don't see also the new error page? I get just this text:
500 Internal Server Error
If you are the administrator of this website, then please read this web application's log file and/or the web server's log file to find out what went wrong.
I see on the logs that is trying to use the application.html.erb, this layout is doing some db calls and that is producing a 500 error, should not use the same layout as the 500? And why is not at least showing the 500 new error page?
I hope someone understand the problem.
Thanks!
Hi, thanks for the message.
You are correct in your assumption, that the "default" 500 error page is raised by the "application" layout's DB calls etc. In terms of why that layout is showing, you will be better doing the following:
config.exception_handler = {
dev: true,
layouts: {
404 => 'exception',
500 => 'exception'
},
}
The "layouts" hash uses integers not strings.
I see on the logs that is trying to use the application.html.erb
If you could show me the logs for this call, I'll be in a much better position to diagnose the error.
--
Looking forward to getting this sorted for you. And thanks again for trying the gem!
Hi, Thanks for your fast answer. The problem was using strings and not integers 😤
Is there a way to make that /500 the 500 new error page render? Now all those static error pages paths are now 404. And how can I test the error pages without triggering an error such the one I want to test?
Thanks for this great gem!
Hmmmm I don't think so.
The behavior you're reporting is actually how it should work (/404 doesn't exist so it goes to a 404 page).
The way I generally test it is to make an obvious error in a method (.each do
), which will then trigger the 500 error page. This will give me the ability to change it to my tastes as required.
Other than that, I guess I could put some functionality into the system but might be hacking it them.
I agree, that the behavior is the way it should work, but we are used to have all those urls (/404, /500 ...). What do you think if for testing we add those routes and we just raise there the http error code? Is any easy why to do something like this?
I add the routes and build a small controller to raise the HTTP Errors, but is not working 😔 The controller try do something like this to show the error pages:
raise ActionController::RoutingError.new('Internal Server Error')
But this is not working. Is there a way I can do that?
Thanks!
Do you have a repo I could look at? Thanks
Sorry, the repo is private. But what I did is really simple.
routes.rb:
get '/500', to: 'p/http_errors#internal_server_error', as: :internal_server_error
http_errors_controller.rb:
class P::HttpErrorsController < P::BaseController
def internal_server_error
raise ActionController::RoutingError.new('Internal Server Error')
end
end
Should work like this? you think it have something to do with my repo?
Thanks!
What happens if you do this...
# config/routes.rb
get '500', controller: 'p/http_errors', action: :internal_server_error, as: :internal_server_error
# config/application.rb
config.exception_handler = { dev: true }
# app/p/controllers/http_errors_controller.rb
class P::HttpErrorsController < P::BaseController
def internal_server_error
raise "Internal Server Error"
end
end
The errors that Rails raises are all mapped to different "HTTP" errors. Any that are not mapped will default to the 500 server error:
Ok, now is almost working: routes.rb
# HTTP Error Pages
#
#
get '401', controller: 'p/http_errors', action: :unauthorized, as: :unauthorized
get '404', controller: 'p/http_errors', action: :not_found, as: :not_found
get '406', controller: 'p/http_errors', action: :not_acceptable, as: :not_acceptable
get '422', controller: 'p/http_errors', action: :unprocessable_entity, as: :unprocessable_entity
get '500', controller: 'p/http_errors', action: :internal_server_error, as: :internal_server_error
http_errors_controller.rb
class P::HttpErrorsController < P::BaseController
def unauthorized
raise ActionController::Unauthorized
end
def not_found
raise ActiveRecord::RecordNotFound
end
def not_acceptable
raise ActionController::UnknownFormat
end
def unprocessable_entity
raise ActionController::InvalidAuthenticityToken
end
def internal_server_error
raise ActionController::InternalServerError
end
end
401 is not working, I need to add it but I am not sure how. And maybe find a better way to raise 500. Can you help me with that?
I think that maybe adding a setting to show error pages even when dev config is false would be a good idea.
For example for development environment, you want to see the standard rails error pages, but is nice to see the pretty ones when you use the static urls (404, 500...), so you can see them without needing to change the global config. What do you think?
BTW: Thanks for all your help and this great gem!
# config/routes.rb
errors = Rack::Utils::HTTP_STATUS_CODES.slice( 401, 404, 406, 422, 500 ) # for some reason slice! won't work
errors.each do |k,v|
value = v.gsub(" ", "").underscore
get k.to_s, to: 'application#http_errors', as: value.to_sym, code: value.to_s # get '500', to: 'p/http_errors#show', as: :internal_server_error, code: "internal_server_error"
end
# config/application.rb
config.action_dispatch.rescue_responses.merge!(
'ApplicationController::NotAuthorized' => :unauthorized,
'ActionController::UnknownFormat' => :not_acceptable,
'ActionController::InternalServerError' => :internal_server_error
)
# app/controllers/application_controller.rb
class P::HttpErrorsController < ActionController::Base
def http_errors
raise Rails.application.config.action_dispatch.rescue_responses.key(params[:code].to_sym).constantize
end
end
As explained in this StackOverflow answer, the big problem is that Rails doesn't handle authorization (or lack of thereof) by default, meaning that if you're trying to invoke a class (which in your case doesn't exist), you will need to create it.
--
For my solution, Rails comes with its own hash of error codes, which means that rather than explicitly defining each error code you're trying to load, you'll be better just slicing this "master" hash.
This has the added benefit of ensuring that you're always 100% compliant with the Rails core.
After this, all you need to do is route all requests to a single controller view (don't repeat yourself), which could actually be put into the "application" controller (which I've demonstrated above). This gives you ultimate flexibility in managing which error codes are raised etc.
Rich
Is not working, but good Idea. For the moment looks like this:
# config/routes.rb
{
401 => :unauthorized,
404 => :not_found,
406 => :not_acceptable,
422 => :unprocessable_entity,
500 => :internal_server_error
}.each do |k,v|
get k.to_s, controller: 'p/http_errors', action: :show, as: v, code: v
end
# config/application.rb
config.action_dispatch.rescue_responses.merge!(
'ApplicationController::NotAuthorized' => :unauthorized,
'ActionController::RecordNotFound' => :not_found,
'ActionController::UnknownFormat' => :not_acceptable,
'ActionController::InvalidAuthenticityToken' => :unprocessable_entity
'ActionController::InternalServerError' => :internal_server_error
)
# app/controllers/p/http_errors_controller.rb
class P::HttpErrorsController < P::BaseController
def show
raise Rails.application.config.action_dispatch.rescue_responses.key( params[:code].to_s )
end
end
And calling for example 422 give me this error:
Started GET "/422" for ::1 at 2018-04-12 14:15:53 +0200
Processing by P::HttpErrorsController#show as HTML
Parameters: {"code"=>:unprocessable_entity}
Completed 500 Internal Server Error in 38ms (ActiveRecord: 9.1ms)
Does the log have any further details about what might be causing the 500 error?
No 😞
I'll have a look this evening
@richpeck Did you have time to test it?
Thanks!
Not yet - had to sort something out. Will test it tonight.
Works fine for me...
Can you show me how did you implemented?
Thanks!
I just copied & pasted the code you had and the code I had.
Ok, I test it again and now works. The only one still not working is 401:
raise ActionController::Unauthorized
This still giving 500 Error page, because ActionController::Unauthorized
do not exist -> errors_rb.html
There is a way around this - using custom exceptions:
Perhaps if you defined something like the following:
#config/application.rb
config.action_dispatch.rescue_responses = {
'ActiveRecord::DangerousAttributeError' => :unauthorized
}
This way, you're able to invoke that particular class and it will be treated as a 401
error.
Still not working... did you try and works for you? Would be nice to have those routes working on development always, like this you can check http pages design without setting dev mode.
No I didn't test
Would be possible to have routes for each error page, but with http status 200?
/500 that you can access?
yes. Just a route /500
where you get the HTTP Error page but with 200 code.
This is coming to the next version -
Thanks!
localhost:3000/404 gives the standard error page. I've been struggling to change this in
routes.rb
, maybe someone can tell me what I'm doing wrong.Every other page gives me my 404 as expected (i'm very pleased overall, besides the exception ive mentioned above):
But also, I don't get my new error page with 500 errors. I get the follow:
How can i make it so that 500 goes to the same page as 400?