From e6a07b69698d7fd23f221c92e50929c0647af706 Mon Sep 17 00:00:00 2001 From: Graham Date: Wed, 1 Dec 2010 18:58:36 -0700 Subject: [PATCH 2/2] Implemented handler-specific options in a way that allows them to be retrieved and used from rackup or any other user of Rack::Server. - Rack handlers that can accept options can now provide a valid_options method that returns a hash of options that can be passed to the handler. - If the hash contains Host or Port, they will be ignored for display by Rack::Server. - Options can be passed in with -O or --option followed by optname=value, or just optname if the option is binary. - rackup -h will display options for the default handler, and rackup -s SERVERNAME -h will display the options for SERVERNAME. --- lib/rack/handler/fastcgi.rb | 8 ++++++++ lib/rack/handler/mongrel.rb | 12 +++++++++++- lib/rack/handler/scgi.rb | 8 ++++++++ lib/rack/handler/thin.rb | 7 +++++++ lib/rack/handler/webrick.rb | 7 +++++++ lib/rack/server.rb | 36 +++++++++++++++++++++++++++++++++++- 6 files changed, 76 insertions(+), 2 deletions(-) diff --git a/lib/rack/handler/fastcgi.rb b/lib/rack/handler/fastcgi.rb index c0be5b4..7737235 100644 --- a/lib/rack/handler/fastcgi.rb +++ b/lib/rack/handler/fastcgi.rb @@ -28,6 +28,14 @@ module Rack serve request, app } end + + def self.valid_options + { + "Host=HOST" => "Hostname to listen on (default: localhost)", + "Port=PORT" => "Port to listen on (default: 8080)", + "File=PATH" => "Creates a Domain socket at PATH instead of a TCP socket. Ignores Host and Port if set.", + } + end def self.serve(request, app) env = request.env diff --git a/lib/rack/handler/mongrel.rb b/lib/rack/handler/mongrel.rb index e437291..d3fea73 100644 --- a/lib/rack/handler/mongrel.rb +++ b/lib/rack/handler/mongrel.rb @@ -38,10 +38,20 @@ module Rack server.run.join end + def self.valid_options + { + "Host=HOST" => "Hostname to listen on (default: localhost)", + "Port=PORT" => "Port to listen on (default: 8080)", + "Processors=N" => "Number of concurrent processors to accept (default: 950)", + "Timeout=N" => "Time before a request is dropped for inactivity (default: 60)", + "Throttle=N" => "Throttle time between socket.accept calls in hundredths of a second (default: 0)", + } + end + def initialize(app) @app = app end - + def process(request, response) env = {}.replace(request.params) env.delete "HTTP_CONTENT_TYPE" diff --git a/lib/rack/handler/scgi.rb b/lib/rack/handler/scgi.rb index 39e23aa..5e53770 100644 --- a/lib/rack/handler/scgi.rb +++ b/lib/rack/handler/scgi.rb @@ -9,11 +9,19 @@ module Rack attr_accessor :app def self.run(app, options=nil) + options[:Socket] = UNIXServer.new(options[:File]) if options[:File] new(options.merge(:app=>app, :host=>options[:Host], :port=>options[:Port], :socket=>options[:Socket])).listen end + + def self.valid_options + { + "Host=HOST" => "Hostname to listen on (default: localhost)", + "Port=PORT" => "Port to listen on (default: 8080)", + } + end def initialize(settings = {}) @app = settings[:app] diff --git a/lib/rack/handler/thin.rb b/lib/rack/handler/thin.rb index b6de4c2..fc110ff 100644 --- a/lib/rack/handler/thin.rb +++ b/lib/rack/handler/thin.rb @@ -12,6 +12,13 @@ module Rack yield server if block_given? server.start end + + def self.valid_options + { + "Host=HOST" => "Hostname to listen on (default: localhost)", + "Port=PORT" => "Port to listen on (default: 8080)", + } + end end end end diff --git a/lib/rack/handler/webrick.rb b/lib/rack/handler/webrick.rb index 342e443..5107a63 100644 --- a/lib/rack/handler/webrick.rb +++ b/lib/rack/handler/webrick.rb @@ -12,6 +12,13 @@ module Rack yield @server if block_given? @server.start end + + def self.valid_options + { + "Host=HOST" => "Hostname to listen on (default: localhost)", + "Port=PORT" => "Port to listen on (default: 8080)", + } + end def self.shutdown @server.shutdown diff --git a/lib/rack/server.rb b/lib/rack/server.rb index 4dada92..f949260 100644 --- a/lib/rack/server.rb +++ b/lib/rack/server.rb @@ -3,6 +3,10 @@ require 'optparse' module Rack class Server class Options + def initialize(server) + @server = server + end + def parse!(args) options = {} opt_parser = OptionParser.new("", 24, ' ') do |opts| @@ -47,6 +51,12 @@ module Rack opts.on("-p", "--port PORT", "use PORT (default: 9292)") { |port| options[:Port] = port } + + opts.on("-O", "--option NAME[=VALUE]", "pass VALUE to the server as option NAME. If no VALUE, sets it to true. Run '#{$0} -s SERVER -h' to get a list of options for SERVER") { |name| + name, value = name.split('=', 2) + value = true if value.nil? + options[name.to_sym] = value + } opts.on("-E", "--env ENVIRONMENT", "use ENVIRONMENT for defaults (default: development)") { |e| options[:environment] = e @@ -65,6 +75,8 @@ module Rack opts.on_tail("-h", "--help", "Show this message") do puts opts + puts handler_opts(options) + exit end @@ -77,6 +89,28 @@ module Rack options[:config] = args.last if args.last options end + + def handler_opts(options) + begin + info = [] + server = Rack::Handler.get(options[:server]) || Rack::Handler.default(options) + if server && server.respond_to?(:valid_options) + info << "" + info << "Server-specific options for #{server.name}:" + + has_options = false + server.valid_options.each do |name, description| + next if name.to_s.match(/^(Host|Port)[^a-zA-Z]/) # ignore handler's host and port options, we do our own. + info << " -O %-21s %s" % [name, description] + has_options = true + end + return "" if !has_options + end + info.join("\n") + rescue NameError + return "Warning: Could not find handler specified (#{options[:server] || 'default'}) to determine handler-specific options" + end + end end # Start a new rack server (like running rackup). This will parse ARGV and @@ -242,7 +276,7 @@ module Rack end def opt_parser - Options.new + Options.new(self) end def build_app(app) -- 1.6.1.2