OSDN Git Service

4afe513faaad9303b2813e3b877d0a3698085ecd
[redminele/redminele.git] / ruby / lib / ruby / gems / 1.8 / gems / rack-1.1.2 / lib / rack / server.rb
1 require 'optparse'
2
3 module Rack
4   class Server
5     class Options
6       def parse!(args)
7         options = {}
8         opt_parser = OptionParser.new("", 24, '  ') do |opts|
9           opts.banner = "Usage: rackup [ruby options] [rack options] [rackup config]"
10
11           opts.separator ""
12           opts.separator "Ruby options:"
13
14           lineno = 1
15           opts.on("-e", "--eval LINE", "evaluate a LINE of code") { |line|
16             eval line, TOPLEVEL_BINDING, "-e", lineno
17             lineno += 1
18           }
19
20           opts.on("-d", "--debug", "set debugging flags (set $DEBUG to true)") {
21             options[:debug] = true
22           }
23           opts.on("-w", "--warn", "turn warnings on for your script") {
24             options[:warn] = true
25           }
26
27           opts.on("-I", "--include PATH",
28                   "specify $LOAD_PATH (may be used more than once)") { |path|
29             options[:include] = path.split(":")
30           }
31
32           opts.on("-r", "--require LIBRARY",
33                   "require the library, before executing your script") { |library|
34             options[:require] = library
35           }
36
37           opts.separator ""
38           opts.separator "Rack options:"
39           opts.on("-s", "--server SERVER", "serve using SERVER (webrick/mongrel)") { |s|
40             options[:server] = s
41           }
42
43           opts.on("-o", "--host HOST", "listen on HOST (default: 0.0.0.0)") { |host|
44             options[:Host] = host
45           }
46
47           opts.on("-p", "--port PORT", "use PORT (default: 9292)") { |port|
48             options[:Port] = port
49           }
50
51           opts.on("-E", "--env ENVIRONMENT", "use ENVIRONMENT for defaults (default: development)") { |e|
52             options[:environment] = e
53           }
54
55           opts.on("-D", "--daemonize", "run daemonized in the background") { |d|
56             options[:daemonize] = d ? true : false
57           }
58
59           opts.on("-P", "--pid FILE", "file to store PID (default: rack.pid)") { |f|
60             options[:pid] = ::File.expand_path(f, Dir.pwd)
61           }
62
63           opts.separator ""
64           opts.separator "Common options:"
65
66           opts.on_tail("-h", "--help", "Show this message") do
67             puts opts
68             exit
69           end
70
71           opts.on_tail("--version", "Show version") do
72             puts "Rack #{Rack.version}"
73             exit
74           end
75         end
76         opt_parser.parse! args
77         options[:config] = args.last if args.last
78         options
79       end
80     end
81
82     def self.start
83       new.start
84     end
85
86     attr_accessor :options
87
88     def initialize(options = nil)
89       @options = options
90     end
91
92     def options
93       @options ||= parse_options(ARGV)
94     end
95
96     def default_options
97       {
98         :environment => "development",
99         :pid         => nil,
100         :Port        => 9292,
101         :Host        => "0.0.0.0",
102         :AccessLog   => [],
103         :config      => ::File.expand_path("config.ru", Dir.pwd)
104       }
105     end
106
107     def app
108       @app ||= begin
109         if !::File.exist? options[:config]
110           abort "configuration #{options[:config]} not found"
111         end
112
113         app, options = Rack::Builder.parse_file(self.options[:config], opt_parser)
114         self.options.merge! options
115         app
116       end
117     end
118
119     def self.middleware
120       @middleware ||= begin
121         m = Hash.new {|h,k| h[k] = []}
122         m["deployment"].concat  [lambda {|server| server.server =~ /CGI/ ? nil : [Rack::CommonLogger, $stderr] }]
123         m["development"].concat m["deployment"] + [[Rack::ShowExceptions], [Rack::Lint]]
124         m
125       end
126     end
127
128     def middleware
129       self.class.middleware
130     end
131
132     def start
133       if options[:debug]
134         $DEBUG = true
135         require 'pp'
136         p options[:server]
137         pp wrapped_app
138         pp app
139       end
140
141       if options[:warn]
142         $-w = true
143       end
144
145       if includes = options[:include]
146         $LOAD_PATH.unshift *includes
147       end
148
149       if library = options[:require]
150         require library
151       end
152
153       daemonize_app if options[:daemonize]
154       write_pid if options[:pid]
155       server.run wrapped_app, options
156     end
157
158     def server
159       @_server ||= Rack::Handler.get(options[:server]) || Rack::Handler.default
160     end
161
162     private
163       def parse_options(args)
164         options = default_options
165
166         # Don't evaluate CGI ISINDEX parameters.
167         # http://hoohoo.ncsa.uiuc.edu/cgi/cl.html
168         args.clear if ENV.include?("REQUEST_METHOD")
169
170         options.merge! opt_parser.parse! args
171         options
172       end
173
174       def opt_parser
175         Options.new
176       end
177
178       def build_app(app)
179         middleware[options[:environment]].reverse_each do |middleware|
180           middleware = middleware.call(self) if middleware.respond_to?(:call)
181           next unless middleware
182           klass = middleware.shift
183           app = klass.new(app, *middleware)
184         end
185         app
186       end
187
188       def wrapped_app
189         @wrapped_app ||= build_app app
190       end
191
192       def daemonize_app
193         if RUBY_VERSION < "1.9"
194           exit if fork
195           Process.setsid
196           exit if fork
197           Dir.chdir "/"
198           ::File.umask 0000
199           STDIN.reopen "/dev/null"
200           STDOUT.reopen "/dev/null", "a"
201           STDERR.reopen "/dev/null", "a"
202         else
203           Process.daemon
204         end
205       end
206
207       def write_pid
208         ::File.open(options[:pid], 'w'){ |f| f.write("#{Process.pid}") }
209         at_exit { ::File.delete(options[:pid]) if ::File.exist?(options[:pid]) }
210       end
211   end
212 end