# File lib/phusion_passenger/rack/thread_handler_extension.rb, line 65 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 env[HTTP_VERSION] = HTTP_1_1 # Rails somehow modifies env['REQUEST_METHOD'], so we perform the comparison # before the Rack application object is called. is_head_request = env[REQUEST_METHOD] == HEAD begin status, headers, body = @app.call(env) rescue => e if !should_swallow_app_error?(e, socket_wrapper) # It's a good idea to catch application exceptions here because # otherwise maliciously crafted responses can crash the app, # forcing it to be respawned, and thereby effectively DoSing it. print_exception("Rack application object", e) PhusionPassenger.log_request_exception(env, e) end return false end # Application requested a full socket hijack. if env[RACK_HIJACK_IO] # Since the app hijacked the socket, we don't know what state we're # in and we don't know whether we can recover from it, so we don't # catch any exception here. # # The Rack specification doesn't specify whether the body should # be closed when the socket is hijacked. As of February 2 2015, # Puma and Thin close the body, while Unicorn does not. # However, Rack::Lock and possibly many other middlewares count # on the body being closed, as described here: # https://github.com/ngauthier/tubesock/issues/10#issuecomment-72539461 # So we have chosen to close the body. body.close if body && body.respond_to?(:close) return true end # Application requested a partial socket hijack. if hijack_callback = headers[RACK_HIJACK] # We don't catch exceptions here. EPIPE is already handled # by ThreadHandler's #accept_and_process_next_request. # On any other exception, we don't know what state we're # in and we don't know whether we can recover from it. begin headers_output = generate_headers_array(status, headers) headers_output << CONNECTION_CLOSE_CRLF2 connection.writev(headers_output) connection.flush hijacked_socket = env[RACK_HIJACK].call hijack_callback.call(hijacked_socket) return true ensure body.close if body && body.respond_to?(:close) end end begin process_body(env, connection, socket_wrapper, status.to_i, is_head_request, headers, body) rescue => e if !should_swallow_app_error?(e, socket_wrapper) print_exception("Rack response body object", e) PhusionPassenger.log_request_exception(env, e) end ensure begin body.close if body && body.respond_to?(:close) rescue => e if !should_swallow_app_error?(e, socket_wrapper) print_exception("Rack response body object's #close method", e) PhusionPassenger.log_request_exception(env, e) end end end false ensure rewindable_input.close end end
Generated with the Darkfish Rdoc Generator 2.