mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
29648ff60e
Puma has its own configuration file(e.g. `config/puma.rb`). Can define a port and a URL to bind in the configuration file. Therefore, on Rails side, can not grasp which URI to bind finally. Because of that, it may show a URL different from the actually bound URL, so I think that it is better not to show it. Fixes #29880
228 lines
7.2 KiB
Ruby
228 lines
7.2 KiB
Ruby
require "fileutils"
|
|
require "optparse"
|
|
require "action_dispatch"
|
|
require "rails"
|
|
require_relative "../../dev_caching"
|
|
|
|
module Rails
|
|
class Server < ::Rack::Server
|
|
class Options
|
|
def parse!(args)
|
|
Rails::Command::ServerCommand.new([], args).server_options
|
|
end
|
|
end
|
|
|
|
def initialize(options = nil)
|
|
@default_options = options || {}
|
|
super(@default_options)
|
|
set_environment
|
|
end
|
|
|
|
# TODO: this is no longer required but we keep it for the moment to support older config.ru files.
|
|
def app
|
|
@app ||= begin
|
|
app = super
|
|
app.respond_to?(:to_app) ? app.to_app : app
|
|
end
|
|
end
|
|
|
|
def opt_parser
|
|
Options.new
|
|
end
|
|
|
|
def set_environment
|
|
ENV["RAILS_ENV"] ||= options[:environment]
|
|
end
|
|
|
|
def start
|
|
print_boot_information
|
|
trap(:INT) { exit }
|
|
create_tmp_directories
|
|
setup_dev_caching
|
|
log_to_stdout if options[:log_stdout]
|
|
|
|
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]
|
|
end
|
|
|
|
def middleware
|
|
Hash.new([])
|
|
end
|
|
|
|
def default_options
|
|
super.merge(@default_options)
|
|
end
|
|
|
|
private
|
|
def setup_dev_caching
|
|
if options[:environment] == "development"
|
|
Rails::DevCaching.enable_by_argument(options[:caching])
|
|
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))
|
|
end
|
|
end
|
|
|
|
def log_to_stdout
|
|
wrapped_app # touch the app so the logger is set up
|
|
|
|
console = ActiveSupport::Logger.new(STDOUT)
|
|
console.formatter = Rails.logger.formatter
|
|
console.level = Rails.logger.level
|
|
|
|
unless ActiveSupport::Logger.logger_outputs_to?(Rails.logger, STDOUT)
|
|
Rails.logger.extend(ActiveSupport::Logger.broadcast(console))
|
|
end
|
|
end
|
|
|
|
def restart_command
|
|
"bin/rails server #{ARGV.join(' ')}"
|
|
end
|
|
|
|
def use_puma?
|
|
server.to_s == "Rack::Handler::Puma"
|
|
end
|
|
end
|
|
|
|
module Command
|
|
class ServerCommand < Base # :nodoc:
|
|
DEFAULT_PORT = 3000
|
|
DEFAULT_PID_PATH = "tmp/pids/server.pid".freeze
|
|
|
|
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,
|
|
desc: "Binds Rails to the specified IP - defaults to 'localhost' in development and '0.0.0.0' in other environments'.",
|
|
banner: :IP
|
|
class_option :config, aliases: "-c", type: :string, default: "config.ru",
|
|
desc: "Uses a custom rackup configuration.", banner: :file
|
|
class_option :daemon, aliases: "-d", type: :boolean, default: false,
|
|
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 :pid, aliases: "-P", type: :string, default: DEFAULT_PID_PATH,
|
|
desc: "Specifies the PID file."
|
|
class_option "dev-caching", aliases: "-C", type: :boolean, default: nil,
|
|
desc: "Specifies whether to perform caching in development."
|
|
|
|
def initialize(args = [], local_options = {}, config = {})
|
|
@original_options = local_options
|
|
super
|
|
@server = self.args.shift
|
|
@log_stdout = options[:daemon].blank? && (options[:environment] || Rails.env) == "development"
|
|
end
|
|
|
|
def perform
|
|
set_application_directory!
|
|
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
|
|
end
|
|
end
|
|
|
|
no_commands do
|
|
def server_options
|
|
{
|
|
user_supplied_options: user_supplied_options,
|
|
server: @server,
|
|
log_stdout: @log_stdout,
|
|
Port: port,
|
|
Host: host,
|
|
DoNotReverseLookup: true,
|
|
config: options[:config],
|
|
environment: environment,
|
|
daemonize: options[:daemon],
|
|
pid: pid,
|
|
caching: options["dev-caching"],
|
|
restart_cmd: restart_command
|
|
}
|
|
end
|
|
end
|
|
|
|
private
|
|
def user_supplied_options
|
|
@user_supplied_options ||= begin
|
|
# Convert incoming options array to a hash of flags
|
|
# ["-p3001", "-C", "--binding", "127.0.0.1"] # => {"-p"=>true, "-C"=>true, "--binding"=>true}
|
|
user_flag = {}
|
|
@original_options.each do |command|
|
|
if command.to_s.start_with?("--")
|
|
option = command.split("=")[0]
|
|
user_flag[option] = true
|
|
elsif command =~ /\A(-.)/
|
|
user_flag[Regexp.last_match[0]] = true
|
|
end
|
|
end
|
|
|
|
# Collect all options that the user has explicitly defined so we can
|
|
# differentiate them from defaults
|
|
user_supplied_options = []
|
|
self.class.class_options.select do |key, option|
|
|
if option.aliases.any? { |name| user_flag[name] } || user_flag["--#{option.name}"]
|
|
name = option.name.to_sym
|
|
case name
|
|
when :port
|
|
name = :Port
|
|
when :binding
|
|
name = :Host
|
|
when :"dev-caching"
|
|
name = :caching
|
|
when :daemonize
|
|
name = :daemon
|
|
end
|
|
user_supplied_options << name
|
|
end
|
|
end
|
|
user_supplied_options << :Host if ENV["HOST"]
|
|
user_supplied_options << :Port if ENV["PORT"]
|
|
user_supplied_options.uniq
|
|
end
|
|
end
|
|
|
|
def port
|
|
options[:port] || ENV.fetch("PORT", DEFAULT_PORT).to_i
|
|
end
|
|
|
|
def host
|
|
if options[:binding]
|
|
options[:binding]
|
|
else
|
|
default_host = environment == "development" ? "localhost" : "0.0.0.0"
|
|
ENV.fetch("HOST", default_host)
|
|
end
|
|
end
|
|
|
|
def environment
|
|
options[:environment] || Rails::Command.environment
|
|
end
|
|
|
|
def restart_command
|
|
"bin/rails server #{@server} #{@original_options.join(" ")}"
|
|
end
|
|
|
|
def pid
|
|
File.expand_path(options[:pid])
|
|
end
|
|
|
|
def self.banner(*)
|
|
"rails server [puma, thin etc] [options]"
|
|
end
|
|
end
|
|
end
|
|
end
|