| 1 |
require 'rack'
|
| 2 |
|
| 3 |
if ARGV.size > 0 then
|
| 4 |
Dir.chdir ARGV[0]
|
| 5 |
end
|
| 6 |
|
| 7 |
def add_server(dir)
|
| 8 |
def read_field (dir, field, default)
|
| 9 |
file = File.join(dir, field)
|
| 10 |
if File.exists? file then
|
| 11 |
File.open(file).read.chomp
|
| 12 |
else
|
| 13 |
default
|
| 14 |
end
|
| 15 |
end
|
| 16 |
|
| 17 |
return [{
|
| 18 |
:path => read_field(dir, "path", "*"),
|
| 19 |
:domain => read_field(dir, "domain", "*"),
|
| 20 |
:host => read_field(dir, "host", "localhost"),
|
| 21 |
:port => read_field(dir, "port", "80"),
|
| 22 |
:mode => read_field(dir, "mode", "http"),
|
| 23 |
}]
|
| 24 |
end
|
| 25 |
|
| 26 |
def match(spec, str)
|
| 27 |
stack = [[0,0]]
|
| 28 |
while not stack.empty? do
|
| 29 |
i, j = stack.pop
|
| 30 |
if i >= spec.size and j >= str.size then
|
| 31 |
return true
|
| 32 |
elsif i >= spec.size or j >= str.size then
|
| 33 |
next
|
| 34 |
elsif spec[i] == '*' then
|
| 35 |
stack.push([ i, j+1 ])
|
| 36 |
stack.push([ i+1, j+1 ])
|
| 37 |
elsif spec[i] == str[j] then
|
| 38 |
stack.push([ i+1, j+1 ])
|
| 39 |
end
|
| 40 |
end
|
| 41 |
return false
|
| 42 |
end
|
| 43 |
|
| 44 |
def init_paths
|
| 45 |
ss = Dir.new(Dir.pwd).sort.map do |f|
|
| 46 |
unless f.start_with? "." then
|
| 47 |
add_server(f)
|
| 48 |
else
|
| 49 |
[]
|
| 50 |
end
|
| 51 |
end
|
| 52 |
return ss.flatten
|
| 53 |
end
|
| 54 |
|
| 55 |
def find_server(env, paths)
|
| 56 |
paths.each do |s|
|
| 57 |
if match(s[:path], env['PATH_INFO']) and match(s[:domain], env['SERVER_NAME']) then
|
| 58 |
return [ 200, { 'Content-Type' => 'text/html'},
|
| 59 |
[ "Forwarding to #{s[:mode]}://#{s[:host]}:#{s[:port]}" ] ]
|
| 60 |
end
|
| 61 |
end
|
| 62 |
return [ 500, { 'Content-Type' => 'text/html' },
|
| 63 |
[ "Unable to find server to forward to" ] ]
|
| 64 |
end
|
| 65 |
|
| 66 |
def serve_paths(paths)
|
| 67 |
app = Proc.new do |env|
|
| 68 |
find_server(env, paths)
|
| 69 |
end
|
| 70 |
Rack::Handler::WEBrick.run app
|
| 71 |
end
|
| 72 |
|
| 73 |
serve_paths(init_paths)
|