EventMachine::Connection
Connection between the server and client. This class is instanciated by EventMachine on each new connection that is opened.
This is a template async response. N.B. Can't use string for body on 1.9
Allows this connection to be persistent.
# File lib/thin/connection.rb, line 167 def can_persist! @can_persist = true end
Return true if this connection is allowed to stay open and be persistent.
# File lib/thin/connection.rb, line 172 def can_persist? @can_persist end
# File lib/thin/connection.rb, line 136 def close_request_response @request.async_close.succeed if @request.async_close @request.close rescue nil @response.close rescue nil end
Logs catched exception and closes the connection.
# File lib/thin/connection.rb, line 130 def handle_error log "!! Unexpected error while processing request: #{$!.message}" log_error close_connection rescue nil end
Return true if the connection must be left open and ready to be reused for another request.
# File lib/thin/connection.rb, line 178 def persistent? @can_persist && @response.persistent? end
Get the connection ready to process a request.
# File lib/thin/connection.rb, line 34 def post_init @request = Request.new @response = Response.new end
# File lib/thin/connection.rb, line 93 def post_process(result) return unless result result = result.to_a # Status code -1 indicates that we're going to respond later (async). return if result.first == AsyncResponse.first # Set the Content-Length header if possible set_content_length(result) if need_content_length?(result) @response.status, @response.headers, @response.body = *result log "!! Rack application returned nil body. Probably you wanted it to be an empty string?" if @response.body.nil? # Make the response persistent if requested by the client @response.persistent! if @request.persistent? # Send the response @response.each do |chunk| trace { chunk } send_data chunk end rescue Exception handle_error ensure # If the body is being deferred, then terminate afterward. if @response.body.respond_to?(:callback) && @response.body.respond_to?(:errback) @response.body.callback { terminate_request } @response.body.errback { terminate_request } else # Don't terminate the response if we're going async. terminate_request unless result && result.first == AsyncResponse.first end end
# File lib/thin/connection.rb, line 61 def pre_process # Add client info to the request env @request.remote_address = remote_address # Connection may be closed unless the App#call response was a [-1, ...] # It should be noted that connection objects will linger until this # callback is no longer referenced, so be tidy! @request.async_callback = method(:post_process) if @backend.ssl? @request.env["rack.url_scheme"] = "https" if cert = get_peer_cert @request.env['rack.peer_cert'] = cert end end # When we're under a non-async framework like rails, we can still spawn # off async responses using the callback info, so there's little point # in removing this. response = AsyncResponse catch(:async) do # Process the request calling the Rack adapter response = @app.call(@request.env) end response rescue Exception handle_error terminate_request nil # Signal to post_process that the request could not be processed end
Called when all data was received and the request is ready to be processed.
# File lib/thin/connection.rb, line 51 def process if threaded? @request.threaded = true EventMachine.defer(method(:pre_process), method(:post_process)) else @request.threaded = false post_process(pre_process) end end
Called when data is received from the client.
# File lib/thin/connection.rb, line 40 def receive_data(data) trace { data } process if @request.parse(data) rescue InvalidRequest => e log "!! Invalid request" log_error e close_connection end
IP Address of the remote client.
# File lib/thin/connection.rb, line 190 def remote_address socket_address rescue Exception log_error nil end
Does request and response cleanup (closes open IO streams and deletes created temporary files). Re-initializes response and request if client supports persistent connection.
# File lib/thin/connection.rb, line 146 def terminate_request unless persistent? close_connection_after_writing rescue nil close_request_response else close_request_response # Prepare the connection for another request if the client # supports HTTP pipelining (persistent connection). post_init end end
true if app.call will be called inside a thread. You can set all requests as threaded setting Connection#threaded=true or on a per-request case returning true in app.deferred?.
# File lib/thin/connection.rb, line 185 def threaded? @threaded || (@app.respond_to?(:deferred?) && @app.deferred?(@request.env)) end
Called when the connection is unbinded from the socket and can no longer be used to process requests.
# File lib/thin/connection.rb, line 160 def unbind @request.async_close.succeed if @request.async_close @response.body.fail if @response.body.respond_to?(:fail) @backend.connection_finished(self) end
Generated with the Darkfish Rdoc Generator 2.