lib/slinky/proxy_server.rb in slinky-0.4.2 vs lib/slinky/proxy_server.rb in slinky-0.5.0

- old
+ new

@@ -2,27 +2,32 @@ module ProxyServer HTTP_MATCHER = /(GET|POST|PUT|DELETE|HEAD) (.+?)(?= HTTP)/ HOST_MATCHER = /Host: (.+)/ def self.process_proxies proxy_hash - proxy_hash.map{|from, to| + proxy_hash.map{|from, h| begin - [from, URI::parse(to)] + to, opt = h.is_a?(Hash) ? [h.delete("to"), h] : [h, {}] + a = [from, URI::parse(to), opt] rescue $stderr.puts "Invalid proxy setting: #{from} => #{to}".foreground(:red) end }.compact end def self.process_proxy_servers proxies - proxies_servers = proxies.map{|p| [p[1].host, p[1].port]} + proxies.map{|p| [p[1].host, p[1].port]} end def self.find_matcher proxies, path proxies.find{|p| path.start_with?(p[0])} end + def self.rewrite_path path, proxy + path.gsub(/^#{proxy[0]}/, "") + end + def self.replace_path http, old_path, new_path, addition # TODO: This may fail in certain, rare cases addition = addition[0..-2] if addition[-1] == "/" http.gsub(old_path, addition + new_path) end @@ -34,21 +39,24 @@ def self.run proxy_hash, port, slinky_port proxies = process_proxies proxy_hash proxy_servers = process_proxy_servers proxies Proxy.start(:host => "0.0.0.0", :port => port){|conn| + proxy = nil + start_time = nil conn.server :slinky, :host => "127.0.0.1", :port => slinky_port proxy_servers.each{|p| conn.server p, :host => p[0], :port => p[1] } conn.on_data do |data| begin _, path = data.match(ProxyServer::HTTP_MATCHER)[1..2] proxy = ProxyServer.find_matcher(proxies, path) + start_time = Time.now server = if proxy - new_path = path.gsub(/^#{proxy[0]}/, "") + new_path = ProxyServer.rewrite_path path, proxy data = ProxyServer.replace_path(data, path, new_path, proxy[1].path) new_host = proxy[1].select(:host, :port).join(":") data = ProxyServer.replace_host(data, new_host) puts [data, [proxy[1].host, proxy[1].port]].inspect [proxy[1].host, proxy[1].port] @@ -60,10 +68,21 @@ conn.send_data "HTTP/1.1 500 Ooops...something went wrong\r\n" end end conn.on_response do |server, resp| - resp + opt = proxy && proxy[2] + if opt && opt["lag"] + # we want to get as close as possible to opt["lag"], so we + # take into account the lag from the backend server + so_far = Time.now - start_time + time = opt["lag"]/1000.0-so_far + EM.add_timer (time > 0 ? time : 0) do + conn.send_data resp + end + else + resp + end end conn.on_finish do |name| unbind end