Class: SC::Rack::Proxy
- Inherits:
-
Object
- Object
- SC::Rack::Proxy
- Defined in:
- lib/sproutcore/rack/proxy.rb
Overview
Rack application proxies requests as needed for the given project.
Instance Method Summary collapse
- #call(env) ⇒ Object
- #handle_proxy(proxy, proxy_url, env) ⇒ Object
-
#initialize(project) ⇒ Proxy
constructor
A new instance of Proxy.
Constructor Details
#initialize(project) ⇒ Proxy
Returns a new instance of Proxy.
15 16 17 18 |
# File 'lib/sproutcore/rack/proxy.rb', line 15 def initialize(project) @project = project @proxies = project.buildfile.proxies end |
Instance Method Details
#call(env) ⇒ Object
20 21 22 23 24 25 26 27 28 29 30 |
# File 'lib/sproutcore/rack/proxy.rb', line 20 def call(env) url = env['PATH_INFO'] @proxies.each do |proxy, value| if url.match(/^#{Regexp.escape(proxy.to_s)}/) return handle_proxy(value, proxy.to_s, env) end end return [404, {}, "not found"] end |
#handle_proxy(proxy, proxy_url, env) ⇒ Object
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
# File 'lib/sproutcore/rack/proxy.rb', line 32 def handle_proxy(proxy, proxy_url, env) origin_host = env['SERVER_NAME'] # capture the origin host for cookies http_method = env['REQUEST_METHOD'].to_s.downcase url = env['PATH_INFO'] params = env['QUERY_STRING'] # collect headers... headers = {} env.each do |key, value| next unless key =~ /^HTTP_/ key = key.gsub(/^HTTP_/,'').downcase.sub(/^\w/){|l| l.upcase}.gsub(/_(\w)/){|l| "-#{$1.upcase}"} # remove HTTP_, dasherize and titleize headers[key] = value end # Rack documentation says CONTENT_TYPE and CONTENT_LENGTH aren't prefixed by HTTP_ headers['Content-Type'] = env['CONTENT_TYPE'] if env['CONTENT_TYPE'] headers['Content-Length'] = env['CONTENT_LENGTH'] if env['CONTENT_LENGTH'] http_host, http_port = proxy[:to].split(':') http_port = '80' if http_port.nil? # added 4/23/09 per Charles Jolley, corrects problem # when making requests to virtual hosts headers['Host'] = "#{http_host}:#{http_port}" if proxy[:url] url = url.sub(/^#{Regexp.escape proxy_url}/, proxy[:url]) end http_path = [url] http_path << params if params && params.size>0 http_path = http_path.join('?') response = nil no_body_method = %w(delete get copy head move options trace) ::Net::HTTP.start(http_host, http_port) do |http| if no_body_method.include?(http_method) response = http.send(http_method, http_path, headers) else http_body = env['rack.input'].gets || '' response = http.send(http_method, http_path, http_body, headers) end end status = response.code # http status code SC.logger << "~ PROXY: #{http_method.upcase} #{status} #{url} -> http://#{http_host}:#{http_port}#{http_path}\n" # display and construct specific response headers response_headers = {} ignore_headers = ['transfer-encoding', 'keep-alive', 'connection'] response.each do |key, value| next if ignore_headers.include?(key.downcase) # If this is a cookie, strip out the domain. This technically may # break certain scenarios where services try to set cross-domain # cookies, but those services should not be doing that anyway... value.gsub!(/domain=[^\;]+\;? ?/,'') if key.downcase == 'set-cookie' # Location headers should rewrite the hostname if it is included. value.gsub!(/^http:\/\/#{http_host}(:[0-9]+)?\//, "http://#{http_host}/") if key.downcase == 'location' SC.logger << " #{key}: #{value}\n" response_headers[key] = value end return [status, ::Rack::Utils::HeaderHash.new(response_headers), [response.body]] end |