rails 4: custom error pages for 404, 500 and where

2020-01-25 04:30发布

Currently in production im getting 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.

No html in that page nothing.

Where is this code situated? I have no public/500.html or anything in that regard.

In my routes I have:

  get "/404", :to => "errors#error_404"
  get "/422", :to => "errors#error_404"
  get "/500", :to => "errors#error_500"
  get "/505", :to => "errors#error_505"

ErrorsController:

class ErrorsController < ApplicationController

  def sub_layout
    "left"
  end

  def error_404
    render :status => 404, :formats => [:html], :layout => "white", :sub_layout => "left"
  end

  def error_422
    render :status => 422, :formats => [:html], :layout => "white", :sub_layout => "left"
  end

  def error_500
    render :status => 500, :formats => [:html], :layout => "white", :sub_layout => "left"
  end

  def error_505
    render :status => 505, :formats => [:html], :layout => "white", :sub_layout => "left"
  end

end

How to make it load my custom errors always? On some errors it just throw that 2 line text coming somewhere from rails core, I want it to pickup my custom styled error pages every time! how? thx!

4条回答
够拽才男人
2楼-- · 2020-01-25 05:07

The Error you are experiencing is being thrown from

https://github.com/rails/rails/blob/4-0-stable/actionpack/lib/action_dispatch/middleware/show_exceptions.rb#L18-L22

This means, the code your exceptions are getting rescued by are themselves throwing exceptions. You can check your logs for text:

Error during failsafe response:

to identify what the exceptions really are originating from and thus solve your problem.

查看更多
仙女界的扛把子
3楼-- · 2020-01-25 05:10

Error pages in application should be as simple as it possible. Same recommendation concerns their rendering. If your application returns 500 HTTP response code it means that things got wrong already. And there is a chance you could not render error page and display it to user.

Ideally error pages should be a plain HTML served directly by your web server without hitting application server.

Speaking of Rails implementation of this idea. It based on using asset pipeline for precompiling the HTML static pages.

Firstly add new assets type (Rails > 4.1):

# config/initializers/assets.rb

Rails.application.config.assets.precompile += %w(404.html 500.html)
Rails.application.config.assets.paths << Rails.root.join('app/assets/html')
Rails.application.config.assets.register_mime_type('text/html', '.html')

If templating engine is using (e.g. slim, haml), register it via initializer:

# for Slim
Rails.application.assets.register_engine('.slim', Slim::Template)
# for Haml
Rails.application.assets.register_engine('.haml', Tilt::HamlTemplate)

Now you ready to create pretty error pages in app/assets/html directory using your favorite template engine and Rails built-in view helpers.

Tips for production

On production asset pipeline adds digest to compiled assets and stores files under default folder (typically shared/public/assets on production server). You can use capistrano to copy error pages to web server root:

# config/deploy.rb
# Capistrano 3 only

namespace :deploy do
  desc 'Copy compiled error pages to public'
  task :copy_error_pages do
    on roles(:all) do
      %w(404 500).each do |page|
        page_glob = "#{current_path}/public/#{fetch(:assets_prefix)}/#{page}*.html"
        # copy newest asset
        asset_file = capture :ruby, %Q{-e "print Dir.glob('#{page_glob}').max_by { |file| File.mtime(file) }"}
        if asset_file
          execute :cp, "#{asset_file} #{current_path}/public/#{page}.html"
        else
          error "Error #{page} asset does not exist"
        end
      end
    end
  end
  after :finishing, :copy_error_pages
end

And last thing. Tell web server to use these files for certain HTTP error codes (sample nginx configuration):

error_page 500 502 503 504 /500.html;    
error_page 404 /404.html;

Sprocket 3 Update

For Sprocket 3 you need something like this (tested with Rails 5):

# config/environments/production.rb
config.assets.configure do |env|
  env.register_transformer 'text/slim', 'text/html', Slim::Template
  env.register_mime_type 'text/slim', extensions: ['.html']
  env.register_engine '.slim', Slim::Template
end

# config/initializers/assets.rb
Rails.application.config.assets.precompile += %w(404.html 500.html)
Rails.application.config.assets.paths << Rails.root.join('app/assets/html')
查看更多
仙女界的扛把子
4楼-- · 2020-01-25 05:25

Here is latest and quick fix for showing custom 404_error page.

  • Add below lines in development.rb or production.rb as per your env.

config.exceptions_app = self.routes

config.consider_all_requests_local = false

  • Remove all rm public/{404,500,422}.html
  • Create 404.html.erb file in static folder of your rails project. You can add your custom html here.(this will be using your application layout so don't bother about header and footer content)
查看更多
Emotional °昔
5楼-- · 2020-01-25 05:32
登录 后发表回答