class Rack::StreamingProxy::Response

Attributes

client_http_version[RW]
headers[R]
status[R]

Public Class Methods

new(piper) click to toggle source
# File lib/rack/streaming_proxy/response.rb, line 9
def initialize(piper)
  @piper = piper
  @client_http_version = '1.1'
  receive
end

Public Instance Methods

each() { |[size, term, chunk, term].join| ... } click to toggle source

This method is called by Rack itself, to iterate over the proxied contents.

# File lib/rack/streaming_proxy/response.rb, line 16
def each
  if @body_permitted
    term = "\r\n"

    while chunk = read_from_destination
      break if chunk == :done
      if @chunked
        size = chunk.bytesize
        next if size == 0
        if @client_http_version >= '1.1'
          yield [size.to_s(16), term, chunk, term].join
        else
          yield chunk
        end
      else
        yield chunk
      end
    end

    finish

    if @chunked && @client_http_version >= '1.1'
      yield ['0', term, '', term].join
    end
  end
end

Private Instance Methods

finish() click to toggle source

parent needs to wait for the child, or it results in the child process becoming defunct, resulting in zombie processes! This is very important. See: siliconisland.ca/2013/04/26/beware-of-the-zombie-process-apocalypse/

# File lib/rack/streaming_proxy/response.rb, line 70
def finish
  Rack::StreamingProxy::Proxy.log :info, "Parent process #{Process.pid} waiting for child process #{@piper.pid} to exit."
  @piper.wait
end
read_from_destination() click to toggle source
# File lib/rack/streaming_proxy/response.rb, line 75
def read_from_destination
  @piper.gets
end
receive() click to toggle source
# File lib/rack/streaming_proxy/response.rb, line 45
def receive
  # The first item received from the child will either be an HTTP status code or an Exception.
  @status = read_from_destination

  if @status.nil? # This should never happen
    Rack::StreamingProxy::Proxy.log :error, "Parent received unexpected nil status!"
    finish
    raise Rack::StreamingProxy::UnknownError
  elsif @status.kind_of? Exception
    e = @status
    Rack::StreamingProxy::Proxy.log :error, "Parent received an Exception from Child: #{e.class}: #{e.message}"
    finish
    raise e
  end

  Rack::StreamingProxy::Proxy.log :debug, "Parent received: Status = #{@status}."
  @body_permitted = read_from_destination
  Rack::StreamingProxy::Proxy.log :debug, "Parent received: Reponse has body? = #{@body_permitted}."
  @headers = HeaderHash.new(read_from_destination)
  @chunked = (@headers['Transfer-Encoding'] == 'chunked')
  finish unless @body_permitted # If there is a body, finish will be called inside each.
end