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 160 160: def can_persist! 161: @can_persist = true 162: end
Return true if this connection is allowed to stay open and be persistent.
# File lib/thin/connection.rb, line 165 165: def can_persist? 166: @can_persist 167: end
# File lib/thin/connection.rb, line 129 129: def close_request_response 130: @request.async_close.succeed if @request.async_close 131: @request.close rescue nil 132: @response.close rescue nil 133: end
Logs catched exception and closes the connection.
# File lib/thin/connection.rb, line 123 123: def handle_error 124: log "!! Unexpected error while processing request: #{$!.message}" 125: log_error 126: close_connection rescue nil 127: end
Return true if the connection must be left open and ready to be reused for another request.
# File lib/thin/connection.rb, line 171 171: def persistent? 172: @can_persist && @response.persistent? 173: end
Get the connection ready to process a request.
# File lib/thin/connection.rb, line 30 30: def post_init 31: @request = Request.new 32: @response = Response.new 33: end
# File lib/thin/connection.rb, line 89 89: def post_process(result) 90: return unless result 91: result = result.to_a 92: 93: # Status code -1 indicates that we're going to respond later (async). 94: return if result.first == AsyncResponse.first 95: 96: @response.status, @response.headers, @response.body = *result 97: 98: log "!! Rack application returned nil body. Probably you wanted it to be an empty string?" if @response.body.nil? 99: 100: # Make the response persistent if requested by the client 101: @response.persistent! if @request.persistent? 102: 103: # Send the response 104: @response.each do |chunk| 105: trace { chunk } 106: send_data chunk 107: end 108: 109: rescue Exception 110: handle_error 111: ensure 112: # If the body is being deferred, then terminate afterward. 113: if @response.body.respond_to?(:callback) && @response.body.respond_to?(:errback) 114: @response.body.callback { terminate_request } 115: @response.body.errback { terminate_request } 116: else 117: # Don't terminate the response if we're going async. 118: terminate_request unless result && result.first == AsyncResponse.first 119: end 120: end
# File lib/thin/connection.rb, line 57 57: def pre_process 58: # Add client info to the request env 59: @request.remote_address = remote_address 60: 61: # Connection may be closed unless the App#call response was a [-1, ...] 62: # It should be noted that connection objects will linger until this 63: # callback is no longer referenced, so be tidy! 64: @request.async_callback = method(:post_process) 65: 66: if @backend.ssl? 67: @request.env["rack.url_scheme"] = "https" 68: 69: if cert = get_peer_cert 70: @request.env['rack.peer_cert'] = cert 71: end 72: end 73: 74: # When we're under a non-async framework like rails, we can still spawn 75: # off async responses using the callback info, so there's little point 76: # in removing this. 77: response = AsyncResponse 78: catch(:async) do 79: # Process the request calling the Rack adapter 80: response = @app.call(@request.env) 81: end 82: response 83: rescue Exception 84: handle_error 85: terminate_request 86: nil # Signal to post_process that the request could not be processed 87: end
Called when all data was received and the request is ready to be processed.
# File lib/thin/connection.rb, line 47 47: def process 48: if threaded? 49: @request.threaded = true 50: EventMachine.defer(method(:pre_process), method(:post_process)) 51: else 52: @request.threaded = false 53: post_process(pre_process) 54: end 55: end
Called when data is received from the client.
# File lib/thin/connection.rb, line 36 36: def receive_data(data) 37: trace { data } 38: process if @request.parse(data) 39: rescue InvalidRequest => e 40: log "!! Invalid request" 41: log_error e 42: close_connection 43: end
IP Address of the remote client.
# File lib/thin/connection.rb, line 183 183: def remote_address 184: socket_address 185: rescue Exception 186: log_error 187: nil 188: 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 139 139: def terminate_request 140: unless persistent? 141: close_connection_after_writing rescue nil 142: close_request_response 143: else 144: close_request_response 145: # Prepare the connection for another request if the client 146: # supports HTTP pipelining (persistent connection). 147: post_init 148: end 149: 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 178 178: def threaded? 179: @threaded || (@app.respond_to?(:deferred?) && @app.deferred?(@request.env)) 180: 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 153 153: def unbind 154: @request.async_close.succeed if @request.async_close 155: @response.body.fail if @response.body.respond_to?(:fail) 156: @backend.connection_finished(self) 157: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.