123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164 |
- #!/usr/bin/env ruby
- require 'optparse'
- env = ENV['RACK_ENV'] || 'development'
- browse = false
- server = nil
- public_dir = 'public' if File.directory?('public')
- options = {:Port => 9393, :Host => '127.0.0.1', :AccessLog => [], :Path => '/'}
- opts = OptionParser.new("", 24, ' ') { |opts|
- opts.banner = "Usage: shotgun [ruby options] [rack options] [rackup config]"
- opts.separator ""
- opts.separator "Ruby options:"
- lineno = 1
- opts.on("-e", "--eval LINE", "evaluate a LINE of code") { |line|
- eval line, TOPLEVEL_BINDING, "-e", lineno
- lineno += 1
- }
- opts.on("-d", "--debug", "set debugging flags (set $DEBUG to true)") {
- $DEBUG = true
- }
- opts.on("-w", "--warn", "turn warnings on for your script") {
- $-w = true
- }
- opts.on("-I", "--include PATH",
- "specify $LOAD_PATH (may be used more than once)") { |path|
- $LOAD_PATH.unshift(*path.split(":"))
- }
- opts.on("-r", "--require LIBRARY",
- "require the library, before executing your script") { |library|
- require library
- }
- opts.separator ""
- opts.separator "Rack options:"
- opts.on("-s", "--server SERVER", "server (webrick, mongrel, thin, etc.)") { |s|
- server = s
- }
- opts.on("-o", "--host HOST", "listen on HOST (default: 127.0.0.1)") { |host|
- options[:Host] = host
- }
- opts.on("-p", "--port PORT", "use PORT (default: 9393)") { |port|
- options[:Port] = port
- }
- opts.on("-E", "--env ENVIRONMENT", "use ENVIRONMENT for defaults (default: development)") { |e|
- env = e
- }
- opts.separator ""
- opts.separator "Shotgun options:"
- opts.on("-O", "--browse", "open browser immediately after starting") { |browse|
- browse = true
- }
- opts.on("-u", "--url URL", "specify url path (default: /)") { |url|
- options[:Path] = url
- }
- opts.on("-P", "--public PATH", "serve static files under PATH") { |path|
- public_dir = path
- }
- opts.on_tail("-h", "--help", "show this message") do
- puts opts
- exit
- end
- opts.on_tail("--version", "show version") do
- require 'rack'
- puts "Rack #{Rack.version}"
- exit
- end
- opts.parse! ARGV
- }
- config = ARGV[0] || "config.ru"
- abort "configuration #{config} not found" unless File.exist? config
- # extract additional arguments from first #\ line in config file.
- if File.read(config)[/^#\\(.*)/]
- opts.parse! $1.split(/\s+/)
- end
- # use the BROWSER environment variable or fall back to a more or less standard
- # set of commands
- ENV['BROWSER'] ||=
- %w[open xdg-open x-www-browser firefox opera mozilla netscape].find do |comm|
- next if comm == 'open' && `uname` !~ /Darwin/
- ENV['PATH'].split(':').any? { |dir| File.executable?("#{dir}/#{comm}") }
- end
- ENV['RACK_ENV'] = env
- require 'rack'
- require 'rack/utils'
- require 'rack/request'
- require 'rack/response'
- require 'rack/lint'
- require 'rack/commonlogger'
- require 'rack/showexceptions'
- require 'shotgun'
- require 'thin' if server.to_s.downcase == 'thin'
- server = Rack::Handler.get(server) || Rack::Handler.default
- app =
- Rack::Builder.new do
- # these middleware run in the master process.
- use Shotgun::Static, public_dir if public_dir
- use Shotgun::SkipFavicon
- # loader forks the child and runs the embedded config followed by the
- # application config.
- run Shotgun::Loader.new(config) {
- case env
- when 'development'
- use Rack::CommonLogger, STDERR unless server.name =~ /CGI/
- use Rack::ShowExceptions
- use Rack::Lint
- when 'deployment', 'production'
- use Rack::CommonLogger, STDERR unless server.name =~ /CGI/
- end
- }
- end
- Shotgun.enable_copy_on_write
- # trap exit signals
- downward = false
- ['INT', 'TERM', 'QUIT'].each do |signal|
- trap(signal) do
- exit! if downward
- downward = true
- server.shutdown if server.respond_to?(:shutdown)
- Process.wait rescue nil
- exit!
- end
- end
- # load shotgun.rb in current working directory if it exists
- Shotgun.preload
- base_url = "http://#{options[:Host]}:#{options[:Port]}#{options[:Path]}"
- puts "== Shotgun/#{server.to_s.sub(/Rack::Handler::/, '')} on #{base_url}"
- server.run app, options do |inst|
- if browse
- if ENV['BROWSER']
- system "#{ENV['BROWSER']} '#{base_url}'"
- else
- abort "BROWSER environment variable not set and no browser detected"
- end
- end
- end
|