class Rack::StreamingProxy::Proxy
Attributes
log_verbosity[RW]
logger[RW]
num_retries_on_5xx[RW]
raise_on_5xx[RW]
Public Class Methods
log(level, message)
click to toggle source
# File lib/rack/streaming_proxy/proxy.rb, line 32 def log(level, message) unless log_verbosity == :low && level == :debug @logger.send level, "[Rack::StreamingProxy] #{message}" end end
new(app, &block)
click to toggle source
The block provided to the initializer is given a Rack::Request and should return:
* nil/false to skip the proxy and continue down the stack * a complete uri (with query string if applicable) to proxy to
Example:
use Rack::StreamingProxy::Proxy do |req| if req.path.start_with?('/search') "http://some_other_service/search?#{req.query}" end end
Most headers, request body, and HTTP method are preserved.
# File lib/rack/streaming_proxy/proxy.rb, line 56 def initialize(app, &block) self.class.set_default_configuration @app = app @block = block end
set_default_configuration()
click to toggle source
# File lib/rack/streaming_proxy/proxy.rb, line 12 def set_default_configuration # Logs to stdout by default unless configured with another logger via Railtie. @logger ||= Logger.new(STDOUT) # At :low verbosity by default -- will not output :debug level messages. # :high verbosity outputs :debug level messages. # This is independent of the Logger's log_level, as set in Rails, for example, # although the Logger's level can override this setting. @log_verbosity ||= :low # No retries are performed by default. @num_retries_on_5xx ||= 0 # If the proxy cannot recover from 5xx's through retries (see num_retries_on_5xx), # then it by default passes through the content from the destination # e.g. the Apache error page. If you want an exception to be raised instead so # you can handle it yourself (i.e. display your own error page), set raise_on_5xx to true. @raise_on_5xx ||= false end
Public Instance Methods
call(env)
click to toggle source
# File lib/rack/streaming_proxy/proxy.rb, line 62 def call(env) current_request = Rack::Request.new(env) # Decide whether this request should be proxied. if destination_uri = @block.call(current_request) self.class.log :info, "Starting proxy request to: #{destination_uri}" request = Rack::StreamingProxy::Request.new(destination_uri, current_request) begin response = Rack::StreamingProxy::Session.new(request).start rescue Exception => e # Rescuing only for the purpose of logging to rack.errors log_rack_error(env, e) raise e end # Notify client http version to the instance of Response class. response.client_http_version = env['HTTP_VERSION'].sub(/HTTP\//, '') if env.has_key?('HTTP_VERSION') # Ideally, both a Content-Length header field and a Transfer-Encoding # header field are not expected to be present from servers which # are compliant with RFC2616. However, irresponsible servers may send # both to rack-streaming-proxy. # RFC2616 says if a message is received with both a Transfer-Encoding # header field and a Content-Length header field, the latter MUST be # ignored. So I deleted a Content-Length header here. # # Though there is a case that rack-streaming-proxy deletes both a # Content-Length and a Transfer-Encoding, a client can acknowledge the # end of body by closing the connection when the entire response has # been sent without a Content-Length header. So a Content-Length header # does not have to be required here in our understaing. response.headers.delete('Content-Length') if response.headers.has_key?('Transfer-Encoding') if env.has_key?('HTTP_VERSION') && env['HTTP_VERSION'] < 'HTTP/1.1' # Be compliant with RFC2146 response.headers.delete('Transfer-Encoding') end self.class.log :info, "Finishing proxy request to: #{destination_uri}" [response.status, response.headers, response] # Continue down the middleware stack if the request is not to be proxied. else @app.call(env) end end
Private Instance Methods
log_rack_error(env, e)
click to toggle source
# File lib/rack/streaming_proxy/proxy.rb, line 109 def log_rack_error(env, e) env['rack.errors'].puts e.message env['rack.errors'].puts e.backtrace #.collect { |line| "\t" + line } env['rack.errors'].flush end