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 172 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 177 def can_persist? @can_persist end
# File lib/thin/connection.rb, line 139 def close_request_response @request.async_close.succeed if @request.async_close @request.close rescue nil @response.close rescue nil end
Return true if the connection is open but is not processing any user requests
# File lib/thin/connection.rb, line 189 def idle? @idle end
Return true if the connection must be left open and ready to be reused for another request.
# File lib/thin/connection.rb, line 183 def persistent? @can_persist && @response.persistent? end
Get the connection ready to process a request.
# File lib/thin/connection.rb, line 30 def post_init @request = Request.new @response = Response.new end
# File lib/thin/connection.rb, line 95 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 @response.status, @response.headers, @response.body = *result log_error("Rack application returned nil body. " "Probably you wanted it to be an empty string?") if @response.body.nil? # HEAD requests should not return a body. @response.skip_body! if @request.head? # 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 => e unexpected_error(e) # Close connection since we can't handle response gracefully close_connection 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 63 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 => e unexpected_error(e) # Pass through error response can_persist? && @request.persistent? ? Response::PERSISTENT_ERROR : Response::ERROR end
Called when all data was received and the request is ready to be processed.
# File lib/thin/connection.rb, line 47 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 36 def receive_data(data) @idle = false trace data process if @request.parse(data) rescue InvalidRequest => e log_error("Invalid request", e) post_process Response::BAD_REQUEST end
IP Address of the remote client.
# File lib/thin/connection.rb, line 201 def remote_address socket_address rescue Exception => e log_error('Could not infer remote address', e) nil end
# File lib/thin/connection.rb, line 57 def ssl_verify_peer(cert) # In order to make the cert available later we have to have made at least # a show of verifying it. true 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 149 def terminate_request unless persistent? close_connection_after_writing rescue nil close_request_response else close_request_response # Connection become idle but it's still open @idle = true # 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 196 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 165 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.