diff options
author | Genadi Samokovarov <gsamokovarov@gmail.com> | 2018-02-19 20:31:56 +0200 |
---|---|---|
committer | Genadi Samokovarov <gsamokovarov@gmail.com> | 2018-03-04 17:50:29 +0200 |
commit | 5af643d8d6f8af19a85a34475f40ac18db7c71e9 (patch) | |
tree | e32e0f33589c49b06d523ce514e1263097fb0adb /railties/lib/rails/commands | |
parent | 22a67927f1c3e0fbc6a77b9b1c8892166a171c78 (diff) | |
download | rails-5af643d8d6f8af19a85a34475f40ac18db7c71e9.tar.gz rails-5af643d8d6f8af19a85a34475f40ac18db7c71e9.tar.bz2 rails-5af643d8d6f8af19a85a34475f40ac18db7c71e9.zip |
Introduce explicit rails server handler option
I mistype `rails server production` instead of `rails server -e
production` expecting to lunch a server in the production environment
all the time. However, the signature of `rails server --help` is:
```
Usage:
rails server [puma, thin etc] [options]
```
This means that the `production` argument is being interpreted as a Rack
server handler like Puma, Thin or Unicorn.
Should we argue for the `rails server production`? I'm not sure of the
reasons, but the `rails console production` behavior was deprecated in:
https://github.com/rails/rails/pull/29358, so parity with the existing
`rails console production` usage may not hold anymore.
In any case, this PR introduces an explicit option for the Rack servers
configuration. The option is called `--using` (or `-u` for short) to
avoid the `rails server --server` tantrum.
The new interface of `rails server` is:
```
Usage:
rails server [using] [options]
Options:
-p, [--port=port] # Runs Rails on the specified port - defaults to 3000.
-b, [--binding=IP] # Binds Rails to the specified IP - defaults to 'localhost' in development and '0.0.0.0' in other environments'.
-c, [--config=file] # Uses a custom rackup configuration.
# Default: config.ru
-d, [--daemon], [--no-daemon] # Runs server as a Daemon.
-e, [--environment=name] # Specifies the environment to run this server under (development/test/production).
-u, [--using=name] # Specifies the Rack server used to run the application (thin/puma/webrick).
-P, [--pid=PID] # Specifies the PID file.
# Default: tmp/pids/server.pid
-C, [--dev-caching], [--no-dev-caching] # Specifies whether to perform caching in development.
[--early-hints], [--no-early-hints] # Enables HTTP/2 early hints.
```
As a bonus, if you mistype the server to use, you'll get an
auto-correction message:
```
$ rails s tin
Could not find handler "tin". Maybe you meant "thin" or "cgi"?
Run `rails server --help` for more options.
```
Diffstat (limited to 'railties/lib/rails/commands')
-rw-r--r-- | railties/lib/rails/commands/server/server_command.rb | 88 |
1 files changed, 72 insertions, 16 deletions
diff --git a/railties/lib/rails/commands/server/server_command.rb b/railties/lib/rails/commands/server/server_command.rb index e546fe3e4b..44b26d3846 100644 --- a/railties/lib/rails/commands/server/server_command.rb +++ b/railties/lib/rails/commands/server/server_command.rb @@ -44,7 +44,6 @@ module Rails end def start - print_boot_information trap(:INT) { exit } create_tmp_directories setup_dev_caching @@ -52,9 +51,14 @@ module Rails super ensure - # The '-h' option calls exit before @options is set. - # If we call 'options' with it unset, we get double help banners. - puts "Exiting" unless @options && options[:daemonize] + yield + end + + def serveable? # :nodoc: + server + true + rescue LoadError, NameError + false end def middleware @@ -65,6 +69,10 @@ module Rails super.merge(@default_options) end + def served_url + "#{options[:SSLEnable] ? 'https' : 'http'}://#{host}:#{port}" unless use_puma? + end + private def setup_dev_caching if options[:environment] == "development" @@ -72,13 +80,6 @@ module Rails end end - def print_boot_information - url = "on #{options[:SSLEnable] ? 'https' : 'http'}://#{options[:Host]}:#{options[:Port]}" unless use_puma? - puts "=> Booting #{ActiveSupport::Inflector.demodulize(server)}" - puts "=> Rails #{Rails.version} application starting in #{Rails.env} #{url}" - puts "=> Run `rails server -h` for more startup options" - end - def create_tmp_directories %w(cache pids sockets).each do |dir_to_make| FileUtils.mkdir_p(File.join(Rails.root, "tmp", dir_to_make)) @@ -108,9 +109,15 @@ module Rails module Command class ServerCommand < Base # :nodoc: + # Hard-coding a bunch of handlers here as we don't have a public way of + # querying them from the Rack::Handler registry. + RACK_SERVERS = %w(cgi fastcgi webrick lsws scgi thin puma unicorn) + DEFAULT_PORT = 3000 DEFAULT_PID_PATH = "tmp/pids/server.pid".freeze + argument :using, optional: true + class_option :port, aliases: "-p", type: :numeric, desc: "Runs Rails on the specified port - defaults to 3000.", banner: :port class_option :binding, aliases: "-b", type: :string, @@ -122,6 +129,8 @@ module Rails desc: "Runs server as a Daemon." class_option :environment, aliases: "-e", type: :string, desc: "Specifies the environment to run this server under (development/test/production).", banner: :name + class_option :using, aliases: "-u", type: :string, + desc: "Specifies the Rack server used to run the application (thin/puma/webrick).", banner: :name class_option :pid, aliases: "-P", type: :string, default: DEFAULT_PID_PATH, desc: "Specifies the PID file." class_option "dev-caching", aliases: "-C", type: :boolean, default: nil, @@ -132,19 +141,28 @@ module Rails def initialize(args = [], local_options = {}, config = {}) @original_options = local_options super - @server = self.args.shift + @using = deprecated_positional_rack_server(using) || options[:using] @log_stdout = options[:daemon].blank? && (options[:environment] || Rails.env) == "development" end def perform set_application_directory! prepare_restart + Rails::Server.new(server_options).tap do |server| # Require application after server sets environment to propagate # the --environment option. require APP_PATH Dir.chdir(Rails.application.root) - server.start + + if server.serveable? + print_boot_information(server.server, server.served_url) + server.start do + say "Exiting" unless options[:daemon] + end + else + say rack_server_suggestion(using) + end end end @@ -152,7 +170,7 @@ module Rails def server_options { user_supplied_options: user_supplied_options, - server: @server, + server: using, log_stdout: @log_stdout, Port: port, Host: host, @@ -226,7 +244,7 @@ module Rails end def restart_command - "bin/rails server #{@server} #{@original_options.join(" ")} --restart" + "bin/rails server #{using} #{@original_options.join(" ")} --restart" end def early_hints @@ -238,12 +256,50 @@ module Rails end def self.banner(*) - "rails server [puma, thin etc] [options]" + "rails server [thin/puma/webrick] [options]" end def prepare_restart FileUtils.rm_f(options[:pid]) if options[:restart] end + + def deprecated_positional_rack_server(value) + if value + ActiveSupport::Deprecation.warn(<<-MSG.squish) + Passing the Rack server name as a regular argument is deprecated + and will be removed in the next Rails version. Please, use the -u + option instead. + MSG + value + end + end + + def rack_server_suggestion(server) + if server.in?(RACK_SERVERS) + <<~MSG + Could not load server "#{server}". Maybe you need to the add it to the Gemfile? + + gem "#{server}" + + Run `rails server --help` for more options. + MSG + else + suggestions = Rails::Command::Spellchecker.suggest(server, from: RACK_SERVERS).map(&:inspect) + + <<~MSG + Could not find server "#{server}". Maybe you meant #{suggestions.first} or #{suggestions.second}? + Run `rails server --help` for more options. + MSG + end + end + + def print_boot_information(server, url) + say <<~MSG + => Booting #{ActiveSupport::Inflector.demodulize(server)} + => Rails #{Rails.version} application starting in #{Rails.env} #{url} + => Run `rails server --help` for more startup options + MSG + end end end end |