class Rack::DynamicReverseProxy
Public Class Methods
new(app = nil, &block)
click to toggle source
# File lib/rack/dynamic_reverse_proxy.rb, line 9 def initialize(app = nil, &block) @app = app || lambda {|env| [404, [], []] } @matchers = [] @rules = [] @global_options = { preserve_host: true, x_forwarded_host: true, matching: :all, replace_response_host: false } instance_eval &block if block_given? end
Public Instance Methods
call(env)
click to toggle source
# File lib/rack/dynamic_reverse_proxy.rb, line 22 def call(env) rackreq = Rack::Request.new(env) rule = get_rule(rackreq) # return @app.call(env) if matcher.nil? return @app.call(env) if rule.nil? # proxy(env, rackreq, matcher) proxy(env, rackreq, rule) end
Private Instance Methods
extract_http_request_headers(env)
click to toggle source
# File lib/rack/dynamic_reverse_proxy.rb, line 90 def extract_http_request_headers(env) headers = env.reject do |k, v| !(/^HTTP_[A-Z_]+$/ === k) || v.nil? end.map do |k, v| [reconstruct_header_name(k), v] end.inject(Utils::HeaderHash.new) do |hash, k_v| k, v = k_v hash[k] = v hash end x_forwarded_for = (headers["X-Forwarded-For"].to_s.split(/, +/) << env["REMOTE_ADDR"]).join(", ") headers.merge!("X-Forwarded-For" => x_forwarded_for) end
get_rule(rackreq)
click to toggle source
# File lib/rack/dynamic_reverse_proxy.rb, line 110 def get_rule rackreq rules = @rules.select do |rule| rule.match? rackreq end if rules.length < 1 nil else rules.first end end
proxy(env, source_request, matcher)
click to toggle source
# File lib/rack/dynamic_reverse_proxy.rb, line 34 def proxy(env, source_request, matcher) # uri = matcher.get_uri(source_request.fullpath, env) uri = matcher.get_uri return @app.call(env) if uri.nil? # options = @global_options.dup.merge(matcher.options) options = @global_options.dup # Initialize request target_request = Net::HTTP.const_get(source_request.request_method.capitalize).new(uri.request_uri) # Setup headers target_request_headers = extract_http_request_headers(source_request.env) if options[:preserve_host] target_request_headers['HOST'] = "#{uri.host}:#{uri.port}" end if options[:x_forwarded_host] target_request_headers['X-Forwarded-Host'] = source_request.host target_request_headers['X-Forwarded-Port'] = "#{source_request.port}" end target_request.initialize_http_header(target_request_headers) # Basic auth target_request.basic_auth options[:username], options[:password] if options[:username] and options[:password] # Setup body if target_request.request_body_permitted? && source_request.body source_request.body.rewind target_request.body_stream = source_request.body end target_request.content_length = source_request.content_length || 0 target_request.content_type = source_request.content_type if source_request.content_type # Create a streaming response (the actual network communication is deferred, a.k.a. streamed) target_response = HttpStreamingResponse.new(target_request, uri.host, uri.port) target_response.use_ssl = "https" == uri.scheme # Let rack set the transfer-encoding header response_headers = target_response.headers response_headers.delete('transfer-encoding') # Replace the location header with the proxy domain if response_headers['location'] && options[:replace_response_host] response_location = URI(response_headers['location'][0]) response_location.host = source_request.host response_headers['location'] = response_location.to_s end [target_response.status, response_headers, target_response.body] end
reconstruct_header_name(name)
click to toggle source
# File lib/rack/dynamic_reverse_proxy.rb, line 106 def reconstruct_header_name(name) name.sub(/^HTTP_/, "").gsub("_", "-") end
reverse_proxy_options(options)
click to toggle source
# File lib/rack/dynamic_reverse_proxy.rb, line 122 def reverse_proxy_options options @global_options = options end
reverse_proxy_rule(rule = nil, &block)
click to toggle source
# File lib/rack/dynamic_reverse_proxy.rb, line 126 def reverse_proxy_rule rule = nil, &block if block_given? @rules << ReverseProxyRule.new(block) else @rules << ReverseProxyRule.new(rule) end end