Skip to content
This repository

Rack::File -> Rack::Files #305

Open
wants to merge 3 commits into from

5 participants

Postmodern Kurtis Rainbolt-Greene José Valim James Tucker Aaron Patterson
Postmodern

Renamed Rack::File to Rack::Files, since it can serve arbitrary files from a root directory. Once we can remove Rack::File, we can no longer worry about name conflicts between ::File and Rack::File.

Postmodern

To be clear, I left a lib/rack/file.rb file and Rack::File constant, which can be removed on a major version bump. Although, I'm unsure if or when a deprecation warning message should be added to the lib/rack/file.rb file, or if a deprecation notice in the ChangeLog would suffice?

Kurtis Rainbolt-Greene

This is an intelligent change, and makes literary and context sense.

José Valim
Collaborator

Backwards incompatible. IIRC Rails relies on Rack::File (and potentially others tools besides Rails).

Kurtis Rainbolt-Greene
José Valim
Collaborator

It needs to be deprecated first.

Postmodern

@josevalim Like I said before, I left a Rack::File and rack/file.rb behind specifically for backwards compatibility. I'm leaving it up to the Rack team how they wish to deprecate the constant (I didn't get a clear answer as to how they normally handle deprecations).

James Tucker
Owner

Needs rebasing now. I'm not ignoring this, I'm just trying to decide when I want to pull the trigger. I think my answer is "for rails 4". The main point being, I don't really want to maintain too much heavy deviance and do continual cross-patching. I'll keep you posted ofc.

Postmodern

Rebased! Tests pass.

Should we bring @rkh into this discussion, as changes to Rack can also impact Sinatra? Also, until Rack::File is completely removed, all Rack code will have to continue using the awkward ::File style. There should be a grace period where Rack::File and Rack::Files co-exist.

James Tucker
Owner

The issues will be broad I believe. I'd expect this will also hit ramaze and maybe padrino separately.

Happy to add a deprecation notice in the next 1.4.x release. I'm not sure how long to give it, but I'd like to give it a while to avoid lots of merge issues. On that note, to reduce merge conflicts, I'd prefer to alias to Files first, and move it over when the deprecation is executed. This will save on maintenance time. (see multipart back ports :'( )

James Tucker
Owner

Thanks for rebasing!!!

James Tucker
Owner

Due to signature changes that have already occurred, I'm leaving this until 1.6 at the earliest.

Aaron Patterson
Collaborator

This seems fine to me. AFAIK, master is 1.6. Should we merge this? < @raggi

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
8  README.rdoc
Source Rendered
@@ -65,7 +65,7 @@ applications needs using middleware, for example:
65 65
 * Rack::CommonLogger, for creating Apache-style logfiles.
66 66
 * Rack::ShowException, for catching unhandled exceptions and
67 67
   presenting them in a nice and helpful way with clickable backtrace.
68  
-* Rack::File, for serving static files.
  68
+* Rack::Files, for serving static files.
69 69
 * ...many others!
70 70
 
71 71
 All these components use the same interface, which is described in
@@ -194,7 +194,7 @@ run on port 11211) and memcache-client installed.
194 194
   * Pool sessions, by blink.
195 195
   * OpenID authentication, by blink.
196 196
   * :Port and :File options for opening FastCGI sockets, by blink.
197  
-  * Last-Modified HTTP header for Rack::File, by blink.
  197
+  * Last-Modified HTTP header for Rack::Files, by blink.
198 198
   * Rack::Builder#use now accepts blocks, by Corey Jewett.
199 199
     (See example/protectedlobster.ru)
200 200
   * HTTP status 201 can contain a Content-Type and a body now.
@@ -229,7 +229,7 @@ run on port 11211) and memcache-client installed.
229 229
   * Many bugfixes and small improvements.
230 230
 
231 231
 * January 9th, 2009: Sixth public release 0.9.1.
232  
-  * Fix directory traversal exploits in Rack::File and Rack::Directory.
  232
+  * Fix directory traversal exploits in Rack::Files and Rack::Directory.
233 233
 
234 234
 * April 25th, 2009: Seventh public release 1.0.0.
235 235
   * SPEC change: Rack::VERSION has been pushed to [1,0].
@@ -384,7 +384,7 @@ run on port 11211) and memcache-client installed.
384 384
   * Various mime types added
385 385
   * Rack::MockRequest now supports HEAD
386 386
   * Rack::Directory now supports files that contain RFC3986 reserved chars
387  
-  * Rack::File now only supports GET and HEAD requests
  387
+  * Rack::Files now only supports GET and HEAD requests
388 388
   * Rack::Server#start now passes the block to Rack::Handler::<h>#run
389 389
   * Rack::Static now supports an index option
390 390
   * Added the Teapot status code
5  lib/rack/directory.rb
... ...
@@ -1,6 +1,7 @@
1 1
 require 'time'
2 2
 require 'rack/utils'
3 3
 require 'rack/mime'
  4
+require 'rack/files'
4 5
 
5 6
 module Rack
6 7
   # Rack::Directory serves entries below the +root+ given, according to the
@@ -8,7 +9,7 @@ module Rack
8 9
   # will be presented in an html based index. If a file is found, the env will
9 10
   # be passed to the specified +app+.
10 11
   #
11  
-  # If +app+ is not specified, a Rack::File of the same +root+ will be used.
  12
+  # If +app+ is not specified, a Rack::Files of the same +root+ will be used.
12 13
 
13 14
   class Directory
14 15
     DIR_FILE = "<tr><td class='name'><a href='%s'>%s</a></td><td class='size'>%s</td><td class='type'>%s</td><td class='mtime'>%s</td></tr>"
@@ -44,7 +45,7 @@ class Directory
44 45
 
45 46
     def initialize(root, app=nil)
46 47
       @root = F.expand_path(root)
47  
-      @app = app || Rack::File.new(@root)
  48
+      @app = app || Rack::Files.new(@root)
48 49
     end
49 50
 
50 51
     def call(env)
142  lib/rack/file.rb
... ...
@@ -1,142 +1,6 @@
1  
-require 'time'
2  
-require 'rack/utils'
3  
-require 'rack/mime'
  1
+require 'rack/files'
4 2
 
5 3
 module Rack
6  
-  # Rack::File serves files below the +root+ directory given, according to the
7  
-  # path info of the Rack request.
8  
-  # e.g. when Rack::File.new("/etc") is used, you can access 'passwd' file
9  
-  # as http://localhost:9292/passwd
10  
-  #
11  
-  # Handlers can detect if bodies are a Rack::File, and use mechanisms
12  
-  # like sendfile on the +path+.
13  
-
14  
-  class File
15  
-    SEPS = Regexp.union(*[::File::SEPARATOR, ::File::ALT_SEPARATOR].compact)
16  
-    ALLOWED_VERBS = %w[GET HEAD]
17  
-
18  
-    attr_accessor :root
19  
-    attr_accessor :path
20  
-    attr_accessor :cache_control
21  
-
22  
-    alias :to_path :path
23  
-
24  
-    def initialize(root, cache_control = nil)
25  
-      @root = root
26  
-      @cache_control = cache_control
27  
-    end
28  
-
29  
-    def call(env)
30  
-      dup._call(env)
31  
-    end
32  
-
33  
-    F = ::File
34  
-
35  
-    def _call(env)
36  
-      unless ALLOWED_VERBS.include? env["REQUEST_METHOD"]
37  
-        return fail(405, "Method Not Allowed")
38  
-      end
39  
-
40  
-      @path_info = Utils.unescape(env["PATH_INFO"])
41  
-      parts = @path_info.split SEPS
42  
-
43  
-      parts.inject(0) do |depth, part|
44  
-        case part
45  
-        when '', '.'
46  
-          depth
47  
-        when '..'
48  
-          return fail(404, "Not Found") if depth - 1 < 0
49  
-          depth - 1
50  
-        else
51  
-          depth + 1
52  
-        end
53  
-      end
54  
-
55  
-      @path = F.join(@root, *parts)
56  
-
57  
-      available = begin
58  
-        F.file?(@path) && F.readable?(@path)
59  
-      rescue SystemCallError
60  
-        false
61  
-      end
62  
-
63  
-      if available
64  
-        serving(env)
65  
-      else
66  
-        fail(404, "File not found: #{@path_info}")
67  
-      end
68  
-    end
69  
-
70  
-    def serving(env)
71  
-      last_modified = F.mtime(@path).httpdate
72  
-      return [304, {}, []] if env['HTTP_IF_MODIFIED_SINCE'] == last_modified
73  
-      response = [
74  
-        200,
75  
-        {
76  
-          "Last-Modified"  => last_modified,
77  
-          "Content-Type"   => Mime.mime_type(F.extname(@path), 'text/plain')
78  
-        },
79  
-        env["REQUEST_METHOD"] == "HEAD" ? [] : self
80  
-      ]
81  
-      response[1].merge! 'Cache-Control' => @cache_control if @cache_control
82  
-
83  
-      # NOTE:
84  
-      #   We check via File::size? whether this file provides size info
85  
-      #   via stat (e.g. /proc files often don't), otherwise we have to
86  
-      #   figure it out by reading the whole file into memory.
87  
-      size = F.size?(@path) || Utils.bytesize(F.read(@path))
88  
-
89  
-      ranges = Rack::Utils.byte_ranges(env, size)
90  
-      if ranges.nil? || ranges.length > 1
91  
-        # No ranges, or multiple ranges (which we don't support):
92  
-        # TODO: Support multiple byte-ranges
93  
-        response[0] = 200
94  
-        @range = 0..size-1
95  
-      elsif ranges.empty?
96  
-        # Unsatisfiable. Return error, and file size:
97  
-        response = fail(416, "Byte range unsatisfiable")
98  
-        response[1]["Content-Range"] = "bytes */#{size}"
99  
-        return response
100  
-      else
101  
-        # Partial content:
102  
-        @range = ranges[0]
103  
-        response[0] = 206
104  
-        response[1]["Content-Range"]  = "bytes #{@range.begin}-#{@range.end}/#{size}"
105  
-        size = @range.end - @range.begin + 1
106  
-      end
107  
-
108  
-      response[1]["Content-Length"] = size.to_s
109  
-      response
110  
-    end
111  
-
112  
-    def each
113  
-      F.open(@path, "rb") do |file|
114  
-        file.seek(@range.begin)
115  
-        remaining_len = @range.end-@range.begin+1
116  
-        while remaining_len > 0
117  
-          part = file.read([8192, remaining_len].min)
118  
-          break unless part
119  
-          remaining_len -= part.length
120  
-
121  
-          yield part
122  
-        end
123  
-      end
124  
-    end
125  
-
126  
-    private
127  
-
128  
-    def fail(status, body)
129  
-      body += "\n"
130  
-      [
131  
-        status,
132  
-        {
133  
-          "Content-Type" => "text/plain",
134  
-          "Content-Length" => body.size.to_s,
135  
-          "X-Cascade" => "pass"
136  
-        },
137  
-        [body]
138  
-      ]
139  
-    end
140  
-
141  
-  end
  4
+  # Rack::File is deprecated, please use Rack::Files instead
  5
+  File = Files
142 6
 end
142  lib/rack/files.rb
... ...
@@ -0,0 +1,142 @@
  1
+require 'time'
  2
+require 'rack/utils'
  3
+require 'rack/mime'
  4
+
  5
+module Rack
  6
+  # Rack::Files serves files below the +root+ directory given, according to the
  7
+  # path info of the Rack request.
  8
+  # e.g. when Rack::Files.new("/etc") is used, you can access 'passwd' file
  9
+  # as http://localhost:9292/passwd
  10
+  #
  11
+  # Handlers can detect if bodies are a Rack::Files, and use mechanisms
  12
+  # like sendfile on the +path+.
  13
+
  14
+  class Files
  15
+    SEPS = Regexp.union(*[::File::SEPARATOR, ::File::ALT_SEPARATOR].compact)
  16
+    ALLOWED_VERBS = %w[GET HEAD]
  17
+
  18
+    attr_accessor :root
  19
+    attr_accessor :path
  20
+    attr_accessor :cache_control
  21
+
  22
+    alias :to_path :path
  23
+
  24
+    def initialize(root, cache_control = nil)
  25
+      @root = root
  26
+      @cache_control = cache_control
  27
+    end
  28
+
  29
+    def call(env)
  30
+      dup._call(env)
  31
+    end
  32
+
  33
+    F = ::File
  34
+
  35
+    def _call(env)
  36
+      unless ALLOWED_VERBS.include? env["REQUEST_METHOD"]
  37
+        return fail(405, "Method Not Allowed")
  38
+      end
  39
+
  40
+      @path_info = Utils.unescape(env["PATH_INFO"])
  41
+      parts = @path_info.split SEPS
  42
+
  43
+      parts.inject(0) do |depth, part|
  44
+        case part
  45
+        when '', '.'
  46
+          depth
  47
+        when '..'
  48
+          return fail(404, "Not Found") if depth - 1 < 0
  49
+          depth - 1
  50
+        else
  51
+          depth + 1
  52
+        end
  53
+      end
  54
+
  55
+      @path = F.join(@root, *parts)
  56
+
  57
+      available = begin
  58
+        F.file?(@path) && F.readable?(@path)
  59
+      rescue SystemCallError
  60
+        false
  61
+      end
  62
+
  63
+      if available
  64
+        serving(env)
  65
+      else
  66
+        fail(404, "File not found: #{@path_info}")
  67
+      end
  68
+    end
  69
+
  70
+    def serving(env)
  71
+      last_modified = F.mtime(@path).httpdate
  72
+      return [304, {}, []] if env['HTTP_IF_MODIFIED_SINCE'] == last_modified
  73
+      response = [
  74
+        200,
  75
+        {
  76
+          "Last-Modified"  => last_modified,
  77
+          "Content-Type"   => Mime.mime_type(F.extname(@path), 'text/plain')
  78
+        },
  79
+        env["REQUEST_METHOD"] == "HEAD" ? [] : self
  80
+      ]
  81
+      response[1].merge! 'Cache-Control' => @cache_control if @cache_control
  82
+
  83
+      # NOTE:
  84
+      #   We check via File::size? whether this file provides size info
  85
+      #   via stat (e.g. /proc files often don't), otherwise we have to
  86
+      #   figure it out by reading the whole file into memory.
  87
+      size = F.size?(@path) || Utils.bytesize(F.read(@path))
  88
+
  89
+      ranges = Rack::Utils.byte_ranges(env, size)
  90
+      if ranges.nil? || ranges.length > 1
  91
+        # No ranges, or multiple ranges (which we don't support):
  92
+        # TODO: Support multiple byte-ranges
  93
+        response[0] = 200
  94
+        @range = 0..size-1
  95
+      elsif ranges.empty?
  96
+        # Unsatisfiable. Return error, and file size:
  97
+        response = fail(416, "Byte range unsatisfiable")
  98
+        response[1]["Content-Range"] = "bytes */#{size}"
  99
+        return response
  100
+      else
  101
+        # Partial content:
  102
+        @range = ranges[0]
  103
+        response[0] = 206
  104
+        response[1]["Content-Range"]  = "bytes #{@range.begin}-#{@range.end}/#{size}"
  105
+        size = @range.end - @range.begin + 1
  106
+      end
  107
+
  108
+      response[1]["Content-Length"] = size.to_s
  109
+      response
  110
+    end
  111
+
  112
+    def each
  113
+      F.open(@path, "rb") do |file|
  114
+        file.seek(@range.begin)
  115
+        remaining_len = @range.end-@range.begin+1
  116
+        while remaining_len > 0
  117
+          part = file.read([8192, remaining_len].min)
  118
+          break unless part
  119
+          remaining_len -= part.length
  120
+
  121
+          yield part
  122
+        end
  123
+      end
  124
+    end
  125
+
  126
+    private
  127
+
  128
+    def fail(status, body)
  129
+      body += "\n"
  130
+      [
  131
+        status,
  132
+        {
  133
+          "Content-Type" => "text/plain",
  134
+          "Content-Length" => body.size.to_s,
  135
+          "X-Cascade" => "pass"
  136
+        },
  137
+        [body]
  138
+      ]
  139
+    end
  140
+
  141
+  end
  142
+end
4  lib/rack/sendfile.rb
... ...
@@ -1,4 +1,4 @@
1  
-require 'rack/file'
  1
+require 'rack/files'
2 2
 
3 3
 module Rack
4 4
 
@@ -13,7 +13,7 @@ module Rack
13 13
   #
14 14
   # In order to take advantage of this middleware, the response body must
15 15
   # respond to +to_path+ and the request must include an X-Sendfile-Type
16  
-  # header. Rack::File and other components implement +to_path+ so there's
  16
+  # header. Rack::Files and other components implement +to_path+ so there's
17 17
   # rarely anything you need to do in your application. The X-Sendfile-Type
18 18
   # header is typically set in your web servers configuration. The following
19 19
   # sections attempt to document
6  lib/rack/static.rb
... ...
@@ -1,8 +1,10 @@
  1
+require 'rack/files'
  2
+
1 3
 module Rack
2 4
 
3 5
   # The Rack::Static middleware intercepts requests for static files
4 6
   # (javascript files, images, stylesheets, etc) based on the url prefixes or
5  
-  # route mappings passed in the options, and serves them using a Rack::File
  7
+  # route mappings passed in the options, and serves them using a Rack::Files
6 8
   # object. This allows a Rack stack to serve both static and dynamic content.
7 9
   #
8 10
   # Examples:
@@ -41,7 +43,7 @@ def initialize(app, options={})
41 43
       @index = options[:index]
42 44
       root = options[:root] || Dir.pwd
43 45
       cache_control = options[:cache_control]
44  
-      @file_server = Rack::File.new(root, cache_control)
  46
+      @file_server = Rack::Files.new(root, cache_control)
45 47
     end
46 48
 
47 49
     def overwrite_file_path(path)
4  test/spec_cascade.rb
... ...
@@ -1,5 +1,5 @@
1 1
 require 'rack/cascade'
2  
-require 'rack/file'
  2
+require 'rack/files'
3 3
 require 'rack/lint'
4 4
 require 'rack/urlmap'
5 5
 require 'rack/mock'
@@ -10,7 +10,7 @@ def cascade(*args)
10 10
   end
11 11
   
12 12
   docroot = File.expand_path(File.dirname(__FILE__))
13  
-  app1 = Rack::File.new(docroot)
  13
+  app1 = Rack::Files.new(docroot)
14 14
 
15 15
   app2 = Rack::URLMap.new("/crash" => lambda { |env| raise "boom" })
16 16
 
38  test/spec_file.rb → test/spec_files.rb
... ...
@@ -1,11 +1,11 @@
1  
-require 'rack/file'
  1
+require 'rack/files'
2 2
 require 'rack/mock'
3 3
 
4  
-describe Rack::File do
  4
+describe Rack::Files do
5 5
   DOCROOT = File.expand_path(File.dirname(__FILE__)) unless defined? DOCROOT
6 6
 
7 7
   should "serve files" do
8  
-    res = Rack::MockRequest.new(Rack::Lint.new(Rack::File.new(DOCROOT))).
  8
+    res = Rack::MockRequest.new(Rack::Lint.new(Rack::Files.new(DOCROOT))).
9 9
       get("/cgi/test")
10 10
 
11 11
     res.should.be.ok
@@ -13,7 +13,7 @@
13 13
   end
14 14
 
15 15
   should "set Last-Modified header" do
16  
-    res = Rack::MockRequest.new(Rack::Lint.new(Rack::File.new(DOCROOT))).
  16
+    res = Rack::MockRequest.new(Rack::Lint.new(Rack::Files.new(DOCROOT))).
17 17
       get("/cgi/test")
18 18
 
19 19
     path = File.join(DOCROOT, "/cgi/test")
@@ -24,7 +24,7 @@
24 24
 
25 25
   should "return 304 if file isn't modified since last serve" do
26 26
     path = File.join(DOCROOT, "/cgi/test")
27  
-    res = Rack::MockRequest.new(Rack::Lint.new(Rack::File.new(DOCROOT))).
  27
+    res = Rack::MockRequest.new(Rack::Lint.new(Rack::Files.new(DOCROOT))).
28 28
       get("/cgi/test", 'HTTP_IF_MODIFIED_SINCE' => File.mtime(path).httpdate)
29 29
 
30 30
     res.status.should.equal 304
@@ -33,14 +33,14 @@
33 33
 
34 34
   should "return the file if it's modified since last serve" do
35 35
     path = File.join(DOCROOT, "/cgi/test")
36  
-    res = Rack::MockRequest.new(Rack::Lint.new(Rack::File.new(DOCROOT))).
  36
+    res = Rack::MockRequest.new(Rack::Lint.new(Rack::Files.new(DOCROOT))).
37 37
       get("/cgi/test", 'HTTP_IF_MODIFIED_SINCE' => (File.mtime(path) - 100).httpdate)
38 38
 
39 39
     res.should.be.ok
40 40
   end
41 41
 
42 42
   should "serve files with URL encoded filenames" do
43  
-    res = Rack::MockRequest.new(Rack::Lint.new(Rack::File.new(DOCROOT))).
  43
+    res = Rack::MockRequest.new(Rack::Lint.new(Rack::Files.new(DOCROOT))).
44 44
       get("/cgi/%74%65%73%74") # "/cgi/test"
45 45
 
46 46
     res.should.be.ok
@@ -48,7 +48,7 @@
48 48
   end
49 49
 
50 50
   should "allow safe directory traversal" do
51  
-    req = Rack::MockRequest.new(Rack::Lint.new(Rack::File.new(DOCROOT)))
  51
+    req = Rack::MockRequest.new(Rack::Lint.new(Rack::Files.new(DOCROOT)))
52 52
 
53 53
     res = req.get('/cgi/../cgi/test')
54 54
     res.should.be.successful
@@ -61,7 +61,7 @@
61 61
   end
62 62
 
63 63
   should "not allow unsafe directory traversal" do
64  
-    req = Rack::MockRequest.new(Rack::Lint.new(Rack::File.new(DOCROOT)))
  64
+    req = Rack::MockRequest.new(Rack::Lint.new(Rack::Files.new(DOCROOT)))
65 65
 
66 66
     res = req.get("/../README")
67 67
     res.should.be.client_error
@@ -76,7 +76,7 @@
76 76
   end
77 77
 
78 78
   should "allow files with .. in their name" do
79  
-    req = Rack::MockRequest.new(Rack::Lint.new(Rack::File.new(DOCROOT)))
  79
+    req = Rack::MockRequest.new(Rack::Lint.new(Rack::Files.new(DOCROOT)))
80 80
     res = req.get("/cgi/..test")
81 81
     res.should.be.not_found
82 82
 
@@ -88,7 +88,7 @@
88 88
   end
89 89
 
90 90
   should "not allow unsafe directory traversal with encoded periods" do
91  
-    res = Rack::MockRequest.new(Rack::Lint.new(Rack::File.new(DOCROOT))).
  91
+    res = Rack::MockRequest.new(Rack::Lint.new(Rack::Files.new(DOCROOT))).
92 92
       get("/%2E%2E/README")
93 93
 
94 94
     res.should.be.client_error?
@@ -96,21 +96,21 @@
96 96
   end
97 97
 
98 98
   should "allow safe directory traversal with encoded periods" do
99  
-    res = Rack::MockRequest.new(Rack::Lint.new(Rack::File.new(DOCROOT))).
  99
+    res = Rack::MockRequest.new(Rack::Lint.new(Rack::Files.new(DOCROOT))).
100 100
       get("/cgi/%2E%2E/cgi/test")
101 101
 
102 102
     res.should.be.successful
103 103
   end
104 104
 
105 105
   should "404 if it can't find the file" do
106  
-    res = Rack::MockRequest.new(Rack::Lint.new(Rack::File.new(DOCROOT))).
  106
+    res = Rack::MockRequest.new(Rack::Lint.new(Rack::Files.new(DOCROOT))).
107 107
       get("/cgi/blubb")
108 108
 
109 109
     res.should.be.not_found
110 110
   end
111 111
 
112 112
   should "detect SystemCallErrors" do
113  
-    res = Rack::MockRequest.new(Rack::Lint.new(Rack::File.new(DOCROOT))).
  113
+    res = Rack::MockRequest.new(Rack::Lint.new(Rack::Files.new(DOCROOT))).
114 114
       get("/cgi")
115 115
 
116 116
     res.should.be.not_found
@@ -118,7 +118,7 @@
118 118
 
119 119
   should "return bodies that respond to #to_path" do
120 120
     env = Rack::MockRequest.env_for("/cgi/test")
121  
-    status, _, body = Rack::File.new(DOCROOT).call(env)
  121
+    status, _, body = Rack::Files.new(DOCROOT).call(env)
122 122
 
123 123
     path = File.join(DOCROOT, "/cgi/test")
124 124
 
@@ -130,7 +130,7 @@
130 130
   should "return correct byte range in body" do
131 131
     env = Rack::MockRequest.env_for("/cgi/test")
132 132
     env["HTTP_RANGE"] = "bytes=22-33"
133  
-    res = Rack::MockResponse.new(*Rack::File.new(DOCROOT).call(env))
  133
+    res = Rack::MockResponse.new(*Rack::Files.new(DOCROOT).call(env))
134 134
 
135 135
     res.status.should.equal 206
136 136
     res["Content-Length"].should.equal "12"
@@ -141,7 +141,7 @@
141 141
   should "return error for unsatisfiable byte range" do
142 142
     env = Rack::MockRequest.env_for("/cgi/test")
143 143
     env["HTTP_RANGE"] = "bytes=1234-5678"
144  
-    res = Rack::MockResponse.new(*Rack::File.new(DOCROOT).call(env))
  144
+    res = Rack::MockResponse.new(*Rack::Files.new(DOCROOT).call(env))
145 145
 
146 146
     res.status.should.equal 416
147 147
     res["Content-Range"].should.equal "bytes */193"
@@ -149,14 +149,14 @@
149 149
 
150 150
   should "support cache control options" do
151 151
     env = Rack::MockRequest.env_for("/cgi/test")
152  
-    status, heads, _ = Rack::File.new(DOCROOT, 'public, max-age=38').call(env)
  152
+    status, heads, _ = Rack::Files.new(DOCROOT, 'public, max-age=38').call(env)
153 153
 
154 154
     status.should.equal 200
155 155
     heads['Cache-Control'].should.equal 'public, max-age=38'
156 156
   end
157 157
 
158 158
   should "only support GET and HEAD requests" do
159  
-    req = Rack::MockRequest.new(Rack::Lint.new(Rack::File.new(DOCROOT)))
  159
+    req = Rack::MockRequest.new(Rack::Lint.new(Rack::Files.new(DOCROOT)))
160 160
 
161 161
     forbidden = %w[post put delete]
162 162
     forbidden.each do |method|
Commit_comment_tip

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.