rack 1.1.6 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of rack might be problematic. Click here for more details.

Files changed (105) hide show
  1. data/README +9 -205
  2. data/SPEC +3 -3
  3. data/lib/rack.rb +1 -24
  4. data/lib/rack/auth/abstract/request.rb +1 -5
  5. data/lib/rack/auth/digest/md5.rb +1 -2
  6. data/lib/rack/auth/digest/params.rb +1 -1
  7. data/lib/rack/content_length.rb +1 -1
  8. data/lib/rack/etag.rb +15 -6
  9. data/lib/rack/file.rb +3 -1
  10. data/lib/rack/handler/cgi.rb +8 -7
  11. data/lib/rack/handler/fastcgi.rb +1 -1
  12. data/lib/rack/handler/lsws.rb +1 -1
  13. data/lib/rack/handler/mongrel.rb +1 -1
  14. data/lib/rack/handler/scgi.rb +1 -4
  15. data/lib/rack/handler/webrick.rb +10 -6
  16. data/lib/rack/lint.rb +29 -37
  17. data/lib/rack/mime.rb +2 -0
  18. data/lib/rack/mock.rb +2 -1
  19. data/lib/rack/recursive.rb +4 -0
  20. data/lib/rack/request.rb +8 -6
  21. data/lib/rack/response.rb +1 -0
  22. data/lib/rack/rewindable_input.rb +13 -10
  23. data/lib/rack/sendfile.rb +8 -6
  24. data/lib/rack/server.rb +68 -9
  25. data/lib/rack/session/cookie.rb +1 -10
  26. data/lib/rack/session/memcache.rb +1 -1
  27. data/lib/rack/urlmap.rb +6 -7
  28. data/lib/rack/utils.rb +40 -71
  29. data/rack.gemspec +7 -11
  30. data/spec/cgi/lighttpd.conf +25 -0
  31. data/spec/cgi/rackup_stub.rb +6 -0
  32. data/spec/cgi/sample_rackup.ru +5 -0
  33. data/spec/cgi/test +9 -0
  34. data/spec/cgi/test.fcgi +8 -0
  35. data/spec/cgi/test.ru +5 -0
  36. data/spec/multipart/bad_robots +259 -0
  37. data/spec/multipart/binary +0 -0
  38. data/spec/multipart/empty +10 -0
  39. data/spec/multipart/fail_16384_nofile +814 -0
  40. data/spec/multipart/file1.txt +1 -0
  41. data/spec/multipart/filename_and_modification_param +7 -0
  42. data/spec/multipart/filename_with_escaped_quotes +6 -0
  43. data/spec/multipart/filename_with_escaped_quotes_and_modification_param +7 -0
  44. data/spec/multipart/filename_with_percent_escaped_quotes +6 -0
  45. data/spec/multipart/filename_with_unescaped_quotes +6 -0
  46. data/spec/multipart/ie +6 -0
  47. data/spec/multipart/nested +10 -0
  48. data/spec/multipart/none +9 -0
  49. data/spec/multipart/semicolon +6 -0
  50. data/spec/multipart/text +10 -0
  51. data/spec/rackup/config.ru +31 -0
  52. data/{test/spec_rack_auth_basic.rb → spec/spec_auth_basic.rb} +11 -14
  53. data/{test/spec_rack_auth_digest.rb → spec/spec_auth_digest.rb} +18 -27
  54. data/{test/spec_rack_builder.rb → spec/spec_builder.rb} +49 -10
  55. data/{test/spec_rack_cascade.rb → spec/spec_cascade.rb} +7 -10
  56. data/{test/spec_rack_cgi.rb → spec/spec_cgi.rb} +34 -32
  57. data/{test/spec_rack_chunked.rb → spec/spec_chunked.rb} +8 -10
  58. data/{test/spec_rack_commonlogger.rb → spec/spec_commonlogger.rb} +10 -15
  59. data/{test/spec_rack_conditionalget.rb → spec/spec_conditionalget.rb} +5 -7
  60. data/{test/spec_rack_config.rb → spec/spec_config.rb} +6 -7
  61. data/{test/spec_rack_content_length.rb → spec/spec_content_length.rb} +7 -8
  62. data/{test/spec_rack_content_type.rb → spec/spec_content_type.rb} +5 -6
  63. data/{test/spec_rack_deflater.rb → spec/spec_deflater.rb} +11 -13
  64. data/{test/spec_rack_directory.rb → spec/spec_directory.rb} +6 -10
  65. data/{test/spec_rack_etag.rb → spec/spec_etag.rb} +3 -5
  66. data/{test/spec_rack_fastcgi.rb → spec/spec_fastcgi.rb} +36 -29
  67. data/{test/spec_rack_file.rb → spec/spec_file.rb} +9 -13
  68. data/{test/spec_rack_handler.rb → spec/spec_handler.rb} +10 -12
  69. data/{test/spec_rack_head.rb → spec/spec_head.rb} +3 -3
  70. data/{test/spec_rack_lint.rb → spec/spec_lint.rb} +19 -32
  71. data/{test/spec_rack_lobster.rb → spec/spec_lobster.rb} +9 -11
  72. data/{test/spec_rack_lock.rb → spec/spec_lock.rb} +15 -17
  73. data/{test/spec_rack_logger.rb → spec/spec_logger.rb} +6 -7
  74. data/{test/spec_rack_methodoverride.rb → spec/spec_methodoverride.rb} +15 -17
  75. data/{test/spec_rack_mock.rb → spec/spec_mock.rb} +30 -32
  76. data/{test/spec_rack_mongrel.rb → spec/spec_mongrel.rb} +40 -46
  77. data/{test/spec_rack_nulllogger.rb → spec/spec_nulllogger.rb} +4 -5
  78. data/{test/spec_rack_recursive.rb → spec/spec_recursive.rb} +28 -36
  79. data/{test/spec_rack_request.rb → spec/spec_request.rb} +84 -98
  80. data/{test/spec_rack_response.rb → spec/spec_response.rb} +46 -27
  81. data/spec/spec_rewindable_input.rb +118 -0
  82. data/{test/spec_rack_runtime.rb → spec/spec_runtime.rb} +15 -11
  83. data/{test/spec_rack_sendfile.rb → spec/spec_sendfile.rb} +11 -14
  84. data/{test/spec_rack_session_cookie.rb → spec/spec_session_cookie.rb} +14 -36
  85. data/{test/spec_rack_session_memcache.rb → spec/spec_session_memcache.rb} +32 -26
  86. data/{test/spec_rack_session_pool.rb → spec/spec_session_pool.rb} +36 -31
  87. data/spec/spec_showexceptions.rb +23 -0
  88. data/spec/spec_showstatus.rb +79 -0
  89. data/{test/spec_rack_static.rb → spec/spec_static.rb} +5 -9
  90. data/{test/spec_rack_thin.rb → spec/spec_thin.rb} +30 -35
  91. data/{test/spec_rack_urlmap.rb → spec/spec_urlmap.rb} +6 -8
  92. data/{test/spec_rack_utils.rb → spec/spec_utils.rb} +134 -74
  93. data/{test/spec_rack_webrick.rb → spec/spec_webrick.rb} +28 -36
  94. data/spec/testrequest.rb +77 -0
  95. data/spec/unregistered_handler/rack/handler/unregistered.rb +7 -0
  96. data/spec/unregistered_handler/rack/handler/unregistered_long_one.rb +7 -0
  97. metadata +176 -191
  98. data/RDOX +0 -0
  99. data/lib/rack/adapter/camping.rb +0 -22
  100. data/test/spec_auth.rb +0 -57
  101. data/test/spec_rack_camping.rb +0 -55
  102. data/test/spec_rack_rewindable_input.rb +0 -118
  103. data/test/spec_rack_showexceptions.rb +0 -21
  104. data/test/spec_rack_showstatus.rb +0 -72
  105. data/test/spec_rackup.rb +0 -164
@@ -36,7 +36,7 @@ module Rack
36
36
 
37
37
  rack_input = RewindableInput.new(request.in)
38
38
 
39
- env.update({"rack.version" => [1,1],
39
+ env.update({"rack.version" => Rack::VERSION,
40
40
  "rack.input" => rack_input,
41
41
  "rack.errors" => request.err,
42
42
 
@@ -20,7 +20,7 @@ module Rack
20
20
  rack_input = RewindableInput.new($stdin.read.to_s)
21
21
 
22
22
  env.update(
23
- "rack.version" => [1,1],
23
+ "rack.version" => Rack::VERSION,
24
24
  "rack.input" => rack_input,
25
25
  "rack.errors" => $stderr,
26
26
  "rack.multithread" => false,
@@ -52,7 +52,7 @@ module Rack
52
52
  rack_input = request.body || StringIO.new('')
53
53
  rack_input.set_encoding(Encoding::BINARY) if rack_input.respond_to?(:set_encoding)
54
54
 
55
- env.update({"rack.version" => [1,1],
55
+ env.update({"rack.version" => Rack::VERSION,
56
56
  "rack.input" => rack_input,
57
57
  "rack.errors" => $stderr,
58
58
 
@@ -17,9 +17,6 @@ module Rack
17
17
 
18
18
  def initialize(settings = {})
19
19
  @app = Rack::Chunked.new(Rack::ContentLength.new(settings[:app]))
20
- @log = Object.new
21
- def @log.info(*args); end
22
- def @log.error(*args); end
23
20
  super(settings)
24
21
  end
25
22
 
@@ -36,7 +33,7 @@ module Rack
36
33
  rack_input = StringIO.new(input_body)
37
34
  rack_input.set_encoding(Encoding::BINARY) if rack_input.respond_to?(:set_encoding)
38
35
 
39
- env.update({"rack.version" => [1,1],
36
+ env.update({"rack.version" => Rack::VERSION,
40
37
  "rack.input" => rack_input,
41
38
  "rack.errors" => $stderr,
42
39
  "rack.multithread" => true,
@@ -7,11 +7,15 @@ module Rack
7
7
  class WEBrick < ::WEBrick::HTTPServlet::AbstractServlet
8
8
  def self.run(app, options={})
9
9
  options[:BindAddress] = options.delete(:Host) if options[:Host]
10
- server = ::WEBrick::HTTPServer.new(options)
11
- server.mount "/", Rack::Handler::WEBrick, app
12
- trap(:INT) { server.shutdown }
13
- yield server if block_given?
14
- server.start
10
+ @server = ::WEBrick::HTTPServer.new(options)
11
+ @server.mount "/", Rack::Handler::WEBrick, app
12
+ yield @server if block_given?
13
+ @server.start
14
+ end
15
+
16
+ def self.shutdown
17
+ @server.shutdown
18
+ @server = nil
15
19
  end
16
20
 
17
21
  def initialize(server, app)
@@ -26,7 +30,7 @@ module Rack
26
30
  rack_input = StringIO.new(req.body.to_s)
27
31
  rack_input.set_encoding(Encoding::BINARY) if rack_input.respond_to?(:set_encoding)
28
32
 
29
- env.update({"rack.version" => [1,1],
33
+ env.update({"rack.version" => Rack::VERSION,
30
34
  "rack.input" => rack_input,
31
35
  "rack.errors" => $stderr,
32
36
 
@@ -7,6 +7,7 @@ module Rack
7
7
  class Lint
8
8
  def initialize(app)
9
9
  @app = app
10
+ @content_length = nil
10
11
  end
11
12
 
12
13
  # :stopdoc:
@@ -51,15 +52,16 @@ module Rack
51
52
  check_headers headers
52
53
  ## and the *body*.
53
54
  check_content_type status, headers
54
- check_content_length status, headers, env
55
+ check_content_length status, headers
56
+ @head_request = env["REQUEST_METHOD"] == "HEAD"
55
57
  [status, headers, self]
56
58
  end
57
59
 
58
60
  ## == The Environment
59
61
  def check_env(env)
60
- ## The environment must be an true instance of Hash (no
61
- ## subclassing allowed) that includes CGI-like headers.
62
- ## The application is free to modify the environment.
62
+ ## The environment must be an instance of Hash that includes
63
+ ## CGI-like headers. The application is free to modify the
64
+ ## environment.
63
65
  assert("env #{env.inspect} is not a Hash, but #{env.class}") {
64
66
  env.kind_of? Hash
65
67
  }
@@ -288,10 +290,6 @@ module Rack
288
290
  @input = input
289
291
  end
290
292
 
291
- def size
292
- @input.size
293
- end
294
-
295
293
  ## * +gets+ must be called without arguments and return a string,
296
294
  ## or +nil+ on EOF.
297
295
  def gets(*args)
@@ -481,7 +479,7 @@ module Rack
481
479
  end
482
480
 
483
481
  ## === The Content-Length
484
- def check_content_length(status, headers, env)
482
+ def check_content_length(status, headers)
485
483
  headers.each { |key, value|
486
484
  if key.downcase == 'content-length'
487
485
  ## There must not be a <tt>Content-Length</tt> header when the
@@ -489,49 +487,43 @@ module Rack
489
487
  assert("Content-Length header found in #{status} response, not allowed") {
490
488
  not Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.include? status.to_i
491
489
  }
492
-
493
- bytes = 0
494
- string_body = true
495
-
496
- if @body.respond_to?(:to_ary)
497
- @body.each { |part|
498
- unless part.kind_of?(String)
499
- string_body = false
500
- break
501
- end
502
-
503
- bytes += Rack::Utils.bytesize(part)
504
- }
505
-
506
- if env["REQUEST_METHOD"] == "HEAD"
507
- assert("Response body was given for HEAD request, but should be empty") {
508
- bytes == 0
509
- }
510
- else
511
- if string_body
512
- assert("Content-Length header was #{value}, but should be #{bytes}") {
513
- value == bytes.to_s
514
- }
515
- end
516
- end
517
- end
518
-
519
- return
490
+ @content_length = value
520
491
  end
521
492
  }
522
493
  end
523
494
 
495
+ def verify_content_length(bytes)
496
+ if @head_request
497
+ assert("Response body was given for HEAD request, but should be empty") {
498
+ bytes == 0
499
+ }
500
+ elsif @content_length
501
+ assert("Content-Length header was #{@content_length}, but should be #{bytes}") {
502
+ @content_length == bytes.to_s
503
+ }
504
+ end
505
+ end
506
+
524
507
  ## === The Body
525
508
  def each
526
509
  @closed = false
510
+ bytes = 0
511
+
527
512
  ## The Body must respond to +each+
513
+ assert("Response body must respond to each") do
514
+ @body.respond_to?(:each)
515
+ end
516
+
528
517
  @body.each { |part|
529
518
  ## and must only yield String values.
530
519
  assert("Body yielded non-string value #{part.inspect}") {
531
520
  part.kind_of? String
532
521
  }
522
+ bytes += Rack::Utils.bytesize(part)
533
523
  yield part
534
524
  }
525
+ verify_content_length(bytes)
526
+
535
527
  ##
536
528
  ## The Body itself should not be an instance of String, as this will
537
529
  ## break in Ruby 1.9.
@@ -87,6 +87,7 @@ module Rack
87
87
  ".gif" => "image/gif",
88
88
  ".gz" => "application/x-gzip",
89
89
  ".h" => "text/x-c",
90
+ ".htc" => "text/x-component",
90
91
  ".hh" => "text/x-c",
91
92
  ".htm" => "text/html",
92
93
  ".html" => "text/html",
@@ -186,6 +187,7 @@ module Rack
186
187
  ".vrml" => "model/vrml",
187
188
  ".war" => "application/java-archive",
188
189
  ".wav" => "audio/x-wav",
190
+ ".webm" => "video/webm",
189
191
  ".wma" => "audio/x-ms-wma",
190
192
  ".wmv" => "video/x-ms-wmv",
191
193
  ".wmx" => "video/x-ms-wmx",
@@ -1,5 +1,6 @@
1
1
  require 'uri'
2
2
  require 'stringio'
3
+ require 'rack'
3
4
  require 'rack/lint'
4
5
  require 'rack/utils'
5
6
  require 'rack/response'
@@ -40,7 +41,7 @@ module Rack
40
41
  end
41
42
 
42
43
  DEFAULT_ENV = {
43
- "rack.version" => [1,1],
44
+ "rack.version" => Rack::VERSION,
44
45
  "rack.input" => StringIO.new,
45
46
  "rack.errors" => StringIO.new,
46
47
  "rack.multithread" => true,
@@ -35,6 +35,10 @@ module Rack
35
35
  end
36
36
 
37
37
  def call(env)
38
+ dup._call(env)
39
+ end
40
+
41
+ def _call(env)
38
42
  @script_name = env["SCRIPT_NAME"]
39
43
  @app.call(env.merge('rack.recursive.include' => method(:include)))
40
44
  rescue ForwardRequest => req
@@ -80,11 +80,13 @@ module Rack
80
80
  def script_name=(s); @env["SCRIPT_NAME"] = s.to_s end
81
81
  def path_info=(s); @env["PATH_INFO"] = s.to_s end
82
82
 
83
- def get?; request_method == "GET" end
84
- def post?; request_method == "POST" end
85
- def put?; request_method == "PUT" end
86
- def delete?; request_method == "DELETE" end
87
- def head?; request_method == "HEAD" end
83
+ def delete?; request_method == "DELETE" end
84
+ def get?; request_method == "GET" end
85
+ def head?; request_method == "HEAD" end
86
+ def options?; request_method == "OPTIONS" end
87
+ def post?; request_method == "POST" end
88
+ def put?; request_method == "PUT" end
89
+ def trace?; request_method == "TRACE" end
88
90
 
89
91
  # The set of form-data media-types. Requests that do not indicate
90
92
  # one of the media types presents in this list will not be eligible
@@ -253,7 +255,7 @@ module Rack
253
255
 
254
256
  def ip
255
257
  if addr = @env['HTTP_X_FORWARDED_FOR']
256
- addr.split(',').last.strip
258
+ (addr.split(',').grep(/\d\./).first || @env['REMOTE_ADDR']).to_s.strip
257
259
  else
258
260
  @env['REMOTE_ADDR']
259
261
  end
@@ -1,5 +1,6 @@
1
1
  require 'rack/request'
2
2
  require 'rack/utils'
3
+ require 'time'
3
4
 
4
5
  module Rack
5
6
  # Rack::Response provides a convenient interface to create a Rack
@@ -1,4 +1,6 @@
1
+ # -*- encoding: binary -*-
1
2
  require 'tempfile'
3
+ require 'rack/utils'
2
4
 
3
5
  module Rack
4
6
  # Class which can make any IO object rewindable, including non-rewindable ones. It does
@@ -16,27 +18,27 @@ module Rack
16
18
  @rewindable_io = nil
17
19
  @unlinked = false
18
20
  end
19
-
21
+
20
22
  def gets
21
23
  make_rewindable unless @rewindable_io
22
24
  @rewindable_io.gets
23
25
  end
24
-
26
+
25
27
  def read(*args)
26
28
  make_rewindable unless @rewindable_io
27
29
  @rewindable_io.read(*args)
28
30
  end
29
-
31
+
30
32
  def each(&block)
31
33
  make_rewindable unless @rewindable_io
32
34
  @rewindable_io.each(&block)
33
35
  end
34
-
36
+
35
37
  def rewind
36
38
  make_rewindable unless @rewindable_io
37
39
  @rewindable_io.rewind
38
40
  end
39
-
41
+
40
42
  # Closes this RewindableInput object without closing the originally
41
43
  # wrapped IO oject. Cleans up any temporary resources that this RewindableInput
42
44
  # has created.
@@ -52,9 +54,9 @@ module Rack
52
54
  @rewindable_io = nil
53
55
  end
54
56
  end
55
-
57
+
56
58
  private
57
-
59
+
58
60
  # Ruby's Tempfile class has a bug. Subclass it and fix it.
59
61
  class Tempfile < ::Tempfile
60
62
  def _close
@@ -76,15 +78,16 @@ module Rack
76
78
  @rewindable_io.binmode
77
79
  if filesystem_has_posix_semantics?
78
80
  @rewindable_io.unlink
81
+ raise 'Unlink failed. IO closed.' if @rewindable_io.closed?
79
82
  @unlinked = true
80
83
  end
81
-
84
+
82
85
  buffer = ""
83
86
  while @io.read(1024 * 4, buffer)
84
87
  entire_buffer_written_out = false
85
88
  while !entire_buffer_written_out
86
89
  written = @rewindable_io.write(buffer)
87
- entire_buffer_written_out = written == buffer.size
90
+ entire_buffer_written_out = written == Rack::Utils.bytesize(buffer)
88
91
  if !entire_buffer_written_out
89
92
  buffer.slice!(0 .. written - 1)
90
93
  end
@@ -92,7 +95,7 @@ module Rack
92
95
  end
93
96
  @rewindable_io.rewind
94
97
  end
95
-
98
+
96
99
  def filesystem_has_posix_semantics?
97
100
  RUBY_PLATFORM !~ /(mswin|mingw|cygwin|java)/
98
101
  end
@@ -2,7 +2,9 @@ require 'rack/file'
2
2
 
3
3
  module Rack
4
4
  class File #:nodoc:
5
- alias :to_path :path
5
+ unless instance_methods(false).include?('to_path')
6
+ alias :to_path :path
7
+ end
6
8
  end
7
9
 
8
10
  # = Sendfile
@@ -11,7 +13,7 @@ module Rack
11
13
  # served from a file and replaces it with a server specific X-Sendfile
12
14
  # header. The web server is then responsible for writing the file contents
13
15
  # to the client. This can dramatically reduce the amount of work required
14
- # by the Ruby backend and takes advantage of the web servers optimized file
16
+ # by the Ruby backend and takes advantage of the web server's optimized file
15
17
  # delivery code.
16
18
  #
17
19
  # In order to take advantage of this middleware, the response body must
@@ -31,19 +33,19 @@ module Rack
31
33
  # a private "/files/" area, enable X-Accel-Redirect, and pass the special
32
34
  # X-Sendfile-Type and X-Accel-Mapping headers to the backend:
33
35
  #
34
- # location /files/ {
36
+ # location ~ /files/(.*) {
35
37
  # internal;
36
- # alias /var/www/;
38
+ # alias /var/www/$1;
37
39
  # }
38
40
  #
39
41
  # location / {
40
- # proxy_redirect false;
42
+ # proxy_redirect off;
41
43
  #
42
44
  # proxy_set_header Host $host;
43
45
  # proxy_set_header X-Real-IP $remote_addr;
44
46
  # proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
45
47
  #
46
- # proxy_set_header X-Sendfile-Type X-Accel-Redirect
48
+ # proxy_set_header X-Sendfile-Type X-Accel-Redirect;
47
49
  # proxy_set_header X-Accel-Mapping /files/=/var/www/;
48
50
  #
49
51
  # proxy_pass http://127.0.0.1:8080/;
@@ -57,7 +57,7 @@ module Rack
57
57
  }
58
58
 
59
59
  opts.on("-P", "--pid FILE", "file to store PID (default: rack.pid)") { |f|
60
- options[:pid] = ::File.expand_path(f, Dir.pwd)
60
+ options[:pid] = f
61
61
  }
62
62
 
63
63
  opts.separator ""
@@ -79,12 +79,61 @@ module Rack
79
79
  end
80
80
  end
81
81
 
82
- def self.start
83
- new.start
82
+ # Start a new rack server (like running rackup). This will parse ARGV and
83
+ # provide standard ARGV rackup options, defaulting to load 'config.ru'.
84
+ #
85
+ # Providing an options hash will prevent ARGV parsing and will not include
86
+ # any default options.
87
+ #
88
+ # This method can be used to very easily launch a CGI application, for
89
+ # example:
90
+ #
91
+ # Rack::Server.start(
92
+ # :app => lambda do |e|
93
+ # [200, {'Content-Type' => 'text/html'}, ['hello world']]
94
+ # end,
95
+ # :server => 'cgi'
96
+ # )
97
+ #
98
+ # Further options available here are documented on Rack::Server#initialize
99
+ def self.start(options = nil)
100
+ new(options).start
84
101
  end
85
102
 
86
- attr_accessor :options
87
-
103
+ attr_writer :options
104
+
105
+ # Options may include:
106
+ # * :app
107
+ # a rack application to run (overrides :config)
108
+ # * :config
109
+ # a rackup configuration file path to load (.ru)
110
+ # * :environment
111
+ # this selects the middleware that will be wrapped around
112
+ # your application. Default options available are:
113
+ # - development: CommonLogger, ShowExceptions, and Lint
114
+ # - deployment: CommonLogger
115
+ # - none: no extra middleware
116
+ # note: when the server is a cgi server, CommonLogger is not included.
117
+ # * :server
118
+ # choose a specific Rack::Handler, e.g. cgi, fcgi, webrick
119
+ # * :daemonize
120
+ # if true, the server will daemonize itself (fork, detach, etc)
121
+ # * :pid
122
+ # path to write a pid file after daemonize
123
+ # * :Host
124
+ # the host address to bind to (used by supporting Rack::Handler)
125
+ # * :Port
126
+ # the port to bind to (used by supporting Rack::Handler)
127
+ # * :AccessLog
128
+ # webrick acess log options (or supporting Rack::Handler)
129
+ # * :debug
130
+ # turn on debug output ($DEBUG = true)
131
+ # * :warn
132
+ # turn on warnings ($-w = true)
133
+ # * :include
134
+ # add given paths to $LOAD_PATH
135
+ # * :require
136
+ # require the given libraries
88
137
  def initialize(options = nil)
89
138
  @options = options
90
139
  end
@@ -100,7 +149,7 @@ module Rack
100
149
  :Port => 9292,
101
150
  :Host => "0.0.0.0",
102
151
  :AccessLog => [],
103
- :config => ::File.expand_path("config.ru", Dir.pwd)
152
+ :config => "config.ru"
104
153
  }
105
154
  end
106
155
 
@@ -119,7 +168,7 @@ module Rack
119
168
  def self.middleware
120
169
  @middleware ||= begin
121
170
  m = Hash.new {|h,k| h[k] = []}
122
- m["deployment"].concat [lambda {|server| server.server =~ /CGI/ ? nil : [Rack::CommonLogger, $stderr] }]
171
+ m["deployment"].concat [lambda {|server| server.server.name =~ /CGI/ ? nil : [Rack::CommonLogger, $stderr] }]
123
172
  m["development"].concat m["deployment"] + [[Rack::ShowExceptions], [Rack::Lint]]
124
173
  m
125
174
  end
@@ -143,7 +192,7 @@ module Rack
143
192
  end
144
193
 
145
194
  if includes = options[:include]
146
- $LOAD_PATH.unshift *includes
195
+ $LOAD_PATH.unshift(*includes)
147
196
  end
148
197
 
149
198
  if library = options[:require]
@@ -152,11 +201,20 @@ module Rack
152
201
 
153
202
  daemonize_app if options[:daemonize]
154
203
  write_pid if options[:pid]
204
+
205
+ trap(:INT) do
206
+ if server.respond_to?(:shutdown)
207
+ server.shutdown
208
+ else
209
+ exit
210
+ end
211
+ end
212
+
155
213
  server.run wrapped_app, options
156
214
  end
157
215
 
158
216
  def server
159
- @_server ||= Rack::Handler.get(options[:server]) || Rack::Handler.default
217
+ @_server ||= Rack::Handler.get(options[:server]) || Rack::Handler.default(options)
160
218
  end
161
219
 
162
220
  private
@@ -168,6 +226,7 @@ module Rack
168
226
  args.clear if ENV.include?("REQUEST_METHOD")
169
227
 
170
228
  options.merge! opt_parser.parse! args
229
+ ENV["RACK_ENV"] = options[:environment]
171
230
  options
172
231
  end
173
232