def process_request(env, connection, socket_wrapper, full_http_response)
rewindable_input = PhusionPassenger::Utils::TeeInput.new(connection, env)
begin
env[RACK_VERSION] = RACK_VERSION_VALUE
env[RACK_INPUT] = rewindable_input
env[RACK_ERRORS] = STDERR
env[RACK_MULTITHREAD] = @request_handler.concurrency > 1
env[RACK_MULTIPROCESS] = true
env[RACK_RUN_ONCE] = false
if env[HTTPS] == YES || env[HTTPS] == ON || env[HTTPS] == ONE
env[RACK_URL_SCHEME] = HTTPS_DOWNCASE
else
env[RACK_URL_SCHEME] = HTTP
end
env[RACK_HIJACK_P] = true
env[RACK_HIJACK] = lambda do
env[RACK_HIJACK_IO] ||= begin
connection.stop_simulating_eof!
connection
end
end
begin
status, headers, body = @app.call(env)
rescue => e
if should_reraise_app_error?(e, socket_wrapper)
raise e
elsif !should_swallow_app_error?(e, socket_wrapper)
print_exception("Rack application object", e)
end
return false
end
return true if env[RACK_HIJACK_IO]
begin
if full_http_response
connection.write("HTTP/1.1 #{status.to_i.to_s} Whatever#{CRLF}")
connection.write("Connection: close#{CRLF}")
end
headers_output = [
STATUS, status.to_i.to_s, CRLF
]
headers.each do |key, values|
if values.is_a?(String)
values = values.split(NEWLINE)
elsif key == RACK_HIJACK
next
end
values.each do |value|
headers_output << key
headers_output << NAME_VALUE_SEPARATOR
headers_output << value
headers_output << CRLF
end
end
headers_output << CRLF
if hijack_callback = headers[RACK_HIJACK]
body = nil
connection.writev(headers_output)
connection.flush
hijacked_socket = env[RACK_HIJACK].call
hijack_callback.call(hijacked_socket)
return true
elsif body.is_a?(Array)
connection.writev2(headers_output, body.to_a)
return false
elsif body.is_a?(String)
headers_output << body
connection.writev(headers_output)
return false
else
connection.writev(headers_output)
if body
begin
body.each do |s|
connection.write(s)
end
rescue => e
if should_reraise_app_error?(e, socket_wrapper)
raise e
elsif !should_swallow_app_error?(e, socket_wrapper)
print_exception("Rack body object #each method", e)
end
return false
end
end
return false
end
ensure
body.close if body && body.respond_to?(:close)
end
ensure
rewindable_input.close
end
end