Hatena::ブログ(Diary)

ursmの日記

2008-02-14

WEBrick::HTTPServer のバーチャルホスト機能を使う

るりまの該当ページを見る限り、WEBrick::HTTPServer のインスタンスを複数生成して #virtual_host に渡してやれば良さそうです。

require 'webrick'
include WEBrick

root = HTTPServer.new(:ServerName => 'example.com', :Port => 8776)
root.mount_proc('/') {|req, res| res.body = 'root' }

hoge = HTTPServer.new(:ServerName => 'hoge.example.com', :Port => 8776)
hoge.mount_proc('/') {|req, res| res.body = 'hoge' }

root.virtual_host(hoge)
trap(:INT) { root.shutdown }
root.start
% ruby vhost.rb
[2008-02-15 01:36:54] INFO  WEBrick 1.3.1
[2008-02-15 01:36:54] INFO  ruby 1.8.6 (2007-09-23) [i686-darwin9.1.0]
[2008-02-15 01:36:54] INFO  WEBrick 1.3.1
[2008-02-15 01:36:54] INFO  ruby 1.8.6 (2007-09-23) [i686-darwin9.1.0]
[2008-02-15 01:36:54] WARN  TCPServer Error: Address already in use - bind(2)
[2008-02-15 01:36:54] WARN  TCPServer Error: Address already in use - bind(2)
/opt/local/lib/ruby/1.8/webrick/utils.rb:73:in `initialize': Address already in use - bind(2) (Errno::EADDRINUSE)
        from /opt/local/lib/ruby/1.8/webrick/utils.rb:73:in `new'
        from /opt/local/lib/ruby/1.8/webrick/utils.rb:73:in `create_listeners'
        from /opt/local/lib/ruby/1.8/webrick/utils.rb:70:in `each'
        from /opt/local/lib/ruby/1.8/webrick/utils.rb:70:in `create_listeners'
        from /opt/local/lib/ruby/1.8/webrick/server.rb:75:in `listen'
        from /opt/local/lib/ruby/1.8/webrick/server.rb:63:in `initialize'
        from /opt/local/lib/ruby/1.8/webrick/httpserver.rb:24:in `initialize'
        from vhost.rb:7:in `new'
        from vhost.rb:7

怒られました。ソースを見てみると GenericServer.new ですでに listen しているようです。

試行錯誤の結果、こうすると上手くいきました。

hoge = HTTPServer.new(:ServerName => 'hoge.example.com', :Port => nil, :DoNotListen => true)

要するに、2つ目以降のインスタンスは :DoNotListen => true にしてやれば良いみたいです。私はルータでポート変換を噛ましていたため、:Port => nil も必要でした。