Skip to content

Loading…

Ability for rackup/Rack::Server to accept handler-specific options on the command line #92

Merged
merged 1 commit into from

4 participants

@stormbrew

(originally Ticket 41 on Lighthouse, but pull requests are awesome so I'm moving it over here -- there is history to this patch, so the lighthouse page may be useful reading to see how it got here at http://rack.lighthouseapp.com/projects/22435/tickets/41-patch-improved-rackups-ability-to-handle-handler-specific-options#ticket-41-12).

This patch makes it so that Rack::Server accepts a new command line option, "-O", that will pass the option named to the handler's option hash. It also adds an expectation that handlers provide a method, called valid_options, that returns a hash of potential options and descriptions thereof. This allows for rackup -h to give information about a handler if "-s Handler -h" is passed in (and provides the options for the default handler if not).

@stormbrew stormbrew 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.
7364b87
@josh

-1 to additional handler requirements

@stormbrew

To be clear (because I wasn't in the original description), it doesn't actually require the handler provide a valid_options method, it just uses it if it's there.

@rkh
Official Rack repositories member

I'd rather have rackup -Xkey:value or something.

@stormbrew

I'm not picky on that, but I'd still really like to see this in the official distribution one way or another. I think the handler side of rack needs some serious love at this point, but there seems to be a huge amount of resistance to improving it.

@raggi raggi merged commit f44d954 into rack:master
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Dec 11, 2010
  1. @stormbrew

    Implemented handler-specific options in a way that allows them to be …

    stormbrew committed
    …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.
View
8 lib/rack/handler/fastcgi.rb
@@ -28,6 +28,14 @@ def self.run(app, options={})
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
View
10 lib/rack/handler/mongrel.rb
@@ -38,6 +38,16 @@ def self.run(app, options={})
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
View
8 lib/rack/handler/scgi.rb
@@ -9,11 +9,19 @@ class SCGI < ::SCGI::Processor
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]
View
7 lib/rack/handler/thin.rb
@@ -12,6 +12,13 @@ def self.run(app, options={})
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
View
7 lib/rack/handler/webrick.rb
@@ -12,6 +12,13 @@ def self.run(app, options={})
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
View
30 lib/rack/server.rb
@@ -47,6 +47,12 @@ def parse!(args)
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 +71,8 @@ def parse!(args)
opts.on_tail("-h", "-?", "--help", "Show this message") do
puts opts
+ puts handler_opts(options)
+
exit
end
@@ -84,6 +92,28 @@ def parse!(args)
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
Something went wrong with that request. Please try again.