Time to Read

1分

Rackライブラリ自身に Rack::Static が添付されていますが、これ、ディレクトリを見に行った場合に自動的に「index.html」を見てくれるとか(Apacheで言うDirectoryIndex設定のこと)、そういう気を回してくれないんですね。

あと、普通にWEBrickを使えばいいんという話もあるでしょうけど、Rackアプリケーションとして実装する意味って結構あって、例えば Rack::URLMap なんかと組み合わせたりできたりします。

ということで、 Rack::Directory を少しだけ変更することで実装可能。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#!/usr/bin/env ruby
require 'rack'
require 'rack/contrib'
 
class Rack::StaticSite < Rack::Directory
  def initialize(root, options={})
    super(root, options[:app])
    @index_filenames = (
      case
      when options[:index]
        [options[:index]]
      when options[:indexes] && !options[:indexes].empty?
        options[:indexes]
      else
        ["index.html"]
      end
    )
  end
 
  def list_directory
    @index_filenames.each do |index|
      @stat = F.stat(File.join(@path, index))
      if @stat.file?
        return @app.call(@env.tap{|e| e['PATH_INFO'] = File.join(e['PATH_INFO'], index) })
      end
    end
    Rack::NotFound.new.call(@env)
  end
end
 
if __FILE__ == $0
  Signal.trap(:INT) { exit! }
  app = Rack::Builder.new { run Rack::StaticSite.new(ARGV[0] || ".") }
  Rack::Handler::WEBrick.run app, :Port => 9292
end

Gistはこちら。オプション等はソースから類推してください。コード自体は、微妙に添削可能かもしれません……。

Rack::NotFound は、 rack-contrib gemに含まれています。index.htmlが無いときはディレクトリを見せるようにしたければ、ただ一言 super と唱えればよろしい。

ワンライナーでも試せるよ!

1
wget https://gist.github.com/raw/909366/fa511a3716a83de433ca5c153fa3554476e8ced1/rack-static_site.rb -O- | ruby - public