require 'cgi' require 'net/http' module Rack class Request HEADERS_IGNORED_WHEN_FORWARDING = ['HTTP_HOST', 'HTTP_VERSION'] # Forward this request to a different URL. # # +options+ is a hash of rewrites of the request for the purpose of # forwarding. # You can override the port, path, querystring, data and method to use # with the forwarded request. def forward_to(host, options={}) # Get some info from the request port = options[:port] || self.port path = options[:path] || self.path_info querystring = options[:querystring] || self.query_string data = options[:data] || @env['rack.input'].read method = options[:method] || self.request_method # Construct URI string uri = 'http://' + host + (port ? ":#{port}" : '') + path uri += '?' + querystring unless querystring == '' LOGGER.debug "Preparing to send request to " + uri uri = URI.parse(uri) # Construct the request from the URI http_request = eval("Net::HTTP::" + method[0,1].upcase + method[1..-1].downcase + ".new('#{uri}')") # Add headers headers = {} @env.each do |header_key, header_value| if !(HEADERS_IGNORED_WHEN_FORWARDING.member?(header_key)) if header_key =~ /^HTTP\_/ header_key = normalise_header_key(header_key) elsif header_key =~ /CONTENT_TYPE/ header_key = 'Content-Type' else header_key = nil end headers[header_key] = header_value unless header_key.nil? end end headers.each do |key, value| LOGGER.debug "Adding header #{key} to request before forwarding" http_request.add_field(key, value) end # Set an attribute for the data being sent, so we can show it # when we call to_s on the HTTP request. http_request.data = data LOGGER.debug "Forwarding request: " + http_request.to_s # Send the request http_response = Net::HTTP.start(uri.host, uri.port) do |http| http.request(http_request, data) end # Send back the response from the proxied URL http_response end private # Turn Rack headers into proper HTTP headers def normalise_header_key(header_key) header_key = header_key.gsub("HTTP_", "").gsub("_", "-") if header_key == "SOAPACTION" header_key = "SOAPAction" end header_key end end end