From 9e093d124136b9e3ed0a9184407fdc3afc5d5c3b Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Mon, 9 Jan 2023 14:57:23 +0100 Subject: [PATCH 1/4] Add a default health controller Load balancers and uptime monitors all need a basic endpoint to tell whether the app is up. Here's a good starting point that'll work in many situations. --- railties/lib/rails.rb | 1 + .../rails/app/templates/config/routes.rb.tt | 4 ++++ railties/lib/rails/health_controller.rb | 22 +++++++++++++++++++ 3 files changed, 27 insertions(+) create mode 100644 railties/lib/rails/health_controller.rb diff --git a/railties/lib/rails.rb b/railties/lib/rails.rb index 7b2e333dd1aa..d68a3ef806d5 100644 --- a/railties/lib/rails.rb +++ b/railties/lib/rails.rb @@ -28,6 +28,7 @@ module Rails extend ActiveSupport::Autoload extend ActiveSupport::Benchmarkable + autoload :HealthController autoload :Info autoload :InfoController autoload :MailersController diff --git a/railties/lib/rails/generators/rails/app/templates/config/routes.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/routes.rb.tt index 262ffd54723e..914a065f7e3c 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/routes.rb.tt +++ b/railties/lib/rails/generators/rails/app/templates/config/routes.rb.tt @@ -1,6 +1,10 @@ Rails.application.routes.draw do # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html + # Reveal health status on /up that returns 200 if the app boots with no exceptions, otherwise 500. + # Can be used by load balancers and uptime monitors to verify that the app is live. + get "up" => "rails/health#show" + # Defines the root path route ("/") # root "articles#index" end diff --git a/railties/lib/rails/health_controller.rb b/railties/lib/rails/health_controller.rb new file mode 100644 index 000000000000..83f4abf5879e --- /dev/null +++ b/railties/lib/rails/health_controller.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +class Rails::HealthController < ActionController::Base # :nodoc: + rescue_from(Exception) { render_down } + + def show + render_up + end + + private + def render_up + render html: html_status(color: "green") + end + + def render_down + render html: html_status(color: "red"), status: 500 + end + + def html_status(color:) + %().html_safe + end +end From acd09df0dc7c8330533576bf0fb5efd6101b3bf1 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Mon, 9 Jan 2023 15:00:27 +0100 Subject: [PATCH 2/4] Add CHANGELOG entry --- railties/CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md index 1c4af0f3f6b8..5ae23a8c0052 100644 --- a/railties/CHANGELOG.md +++ b/railties/CHANGELOG.md @@ -1,3 +1,9 @@ +* Add Rails::HealthController#show and map it to /up for newly generated applications. + Load balancers and uptime monitors all need a basic endpoint to tell whether the app is up. + This is a good starting point that'll work in many situations. + + *DHH* + * Only use HostAuthorization middleware if `config.hosts` is not empty *Hartley McGuire* From 557b47c07d9b1aa023d35e276752b40744f514bd Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Mon, 9 Jan 2023 15:04:11 +0100 Subject: [PATCH 3/4] Add test for HealthController --- railties/test/application/routing_test.rb | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/railties/test/application/routing_test.rb b/railties/test/application/routing_test.rb index b2eea19c0818..20407c9a04a5 100644 --- a/railties/test/application/routing_test.rb +++ b/railties/test/application/routing_test.rb @@ -130,6 +130,19 @@ def index assert_equal 404, last_response.status end + test "rails/health in production" do + app("production") + + app_file "config/routes.rb", <<-RUBY + Rails.application.routes.draw do + get "up" => "rails/health#show" + end + RUBY + + get "/up" + assert_equal 200, last_response.status + end + test "simple controller" do simple_controller From 0df2c3c7bd21fd1c22fd9132441e1dab803a78c3 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Mon, 9 Jan 2023 15:21:54 +0100 Subject: [PATCH 4/4] Account for new default route --- railties/test/generators/scaffold_generator_test.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/railties/test/generators/scaffold_generator_test.rb b/railties/test/generators/scaffold_generator_test.rb index cbd41ec72ad5..7e5d8a6e0906 100644 --- a/railties/test/generators/scaffold_generator_test.rb +++ b/railties/test/generators/scaffold_generator_test.rb @@ -361,8 +361,9 @@ def test_scaffold_generator_on_revoke_does_not_mutilate_routes route_path = File.expand_path("config/routes.rb", destination_root) content = File.read(route_path) - # Remove all of the comments and blank lines from the routes file + # Remove all of the comments, blank lines, and default health controller from the routes file content.gsub!(/^ \#.*\n/, "") + content.gsub!(/^ get "up".*\n/, "") content.gsub!(/^\n/, "") File.write(route_path, content)