|  | 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) |