Class: Thin::Connection

Class Thin::Connection < EventMachine::Connection

(in files lib/thin/connection.rb )

Connection between the server and client. This class is instanciated by EventMachine on each new connection that is opened.

Includes

Methods

Public Instance can_persist!()

Allows this connection to be persistent.

     # File lib/thin/connection.rb, line 159
159:     def can_persist!
160:       @can_persist = true
161:     end

Public Instance can_persist?()

Return true if this connection is allowed to stay open and be persistent.

     # File lib/thin/connection.rb, line 164
164:     def can_persist?
165:       @can_persist
166:     end

Public Instance close_request_response()

     # File lib/thin/connection.rb, line 128
128:     def close_request_response
129:       @request.async_close.succeed if @request.async_close
130:       @request.close  rescue nil
131:       @response.close rescue nil
132:     end

Public Instance handle_error()

Logs catched exception and closes the connection.

     # File lib/thin/connection.rb, line 122
122:     def handle_error
123:       log "!! Unexpected error while processing request: #{$!.message}"
124:       log_error
125:       close_connection rescue nil
126:     end

Public Instance persistent?()

Return true if the connection must be left open and ready to be reused for another request.

     # File lib/thin/connection.rb, line 170
170:     def persistent?
171:       @can_persist && @response.persistent?
172:     end

Public Instance post_init()

Get the connection ready to process a request.

    # File lib/thin/connection.rb, line 34
34:     def post_init
35:       @request  = Request.new
36:       @response = Response.new
37:     end

Public Instance post_process(result)

     # File lib/thin/connection.rb, line 85
 85:     def post_process(result)
 86:       return unless result
 87:       result = result.to_a
 88:       
 89:       # Status code -1 indicates that we're going to respond later (async).
 90:       return if result.first == AsyncResponse.first
 91: 
 92:       # Set the Content-Length header if possible
 93:       set_content_length(result) if need_content_length?(result)
 94:       
 95:       @response.status, @response.headers, @response.body = *result
 96: 
 97:       log "!! Rack application returned nil body. Probably you wanted it to be an empty string?" if @response.body.nil?
 98: 
 99:       # Make the response persistent if requested by the client
100:       @response.persistent! if @request.persistent?
101: 
102:       # Send the response
103:       @response.each do |chunk|
104:         trace { chunk }
105:         send_data chunk
106:       end
107: 
108:     rescue Exception
109:       handle_error
110:     ensure
111:       # If the body is being deferred, then terminate afterward.
112:       if @response.body.respond_to?(:callback) && @response.body.respond_to?(:errback)
113:         @response.body.callback { terminate_request }
114:         @response.body.errback  { terminate_request }
115:       else
116:         # Don't terminate the response if we're going async.
117:         terminate_request unless result && result.first == AsyncResponse.first
118:       end
119:     end

Public Instance pre_process()

    # File lib/thin/connection.rb, line 61
61:     def pre_process
62:       # Add client info to the request env
63:       @request.remote_address = remote_address
64: 
65:       # Connection may be closed unless the App#call response was a [-1, ...]
66:       # It should be noted that connection objects will linger until this 
67:       # callback is no longer referenced, so be tidy!
68:       @request.async_callback = method(:post_process)
69:       
70:       # When we're under a non-async framework like rails, we can still spawn
71:       # off async responses using the callback info, so there's little point
72:       # in removing this.
73:       response = AsyncResponse
74:       catch(:async) do
75:         # Process the request calling the Rack adapter
76:         response = @app.call(@request.env)
77:       end
78:       response
79:     rescue Exception
80:       handle_error
81:       terminate_request
82:       nil # Signal to post_process that the request could not be processed
83:     end

Public Instance process()

Called when all data was received and the request is ready to be processed.

    # File lib/thin/connection.rb, line 51
51:     def process
52:       if threaded?
53:         @request.threaded = true
54:         EventMachine.defer(method(:pre_process), method(:post_process))
55:       else
56:         @request.threaded = false
57:         post_process(pre_process)
58:       end
59:     end

Public Instance receive_data(data)

Called when data is received from the client.

    # File lib/thin/connection.rb, line 40
40:     def receive_data(data)
41:       trace { data }
42:       process if @request.parse(data)
43:     rescue InvalidRequest => e
44:       log "!! Invalid request"
45:       log_error e
46:       close_connection
47:     end

Public Instance remote_address()

IP Address of the remote client.

     # File lib/thin/connection.rb, line 182
182:     def remote_address
183:       @request.forwarded_for || socket_address
184:     rescue Exception
185:       log_error
186:       nil
187:     end

Public Instance terminate_request()

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 138
138:     def terminate_request
139:       unless persistent?
140:         close_connection_after_writing rescue nil
141:         close_request_response
142:       else
143:         close_request_response
144:         # Prepare the connection for another request if the client
145:         # supports HTTP pipelining (persistent connection).
146:         post_init
147:       end
148:     end

Public Instance threaded?()

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 177
177:     def threaded?
178:       @threaded || (@app.respond_to?(:deferred?) && @app.deferred?(@request.env))
179:     end

Public Instance unbind()

Called when the connection is unbinded from the socket and can no longer be used to process requests.

     # File lib/thin/connection.rb, line 152
152:     def unbind
153:       @request.async_close.succeed if @request.async_close
154:       @response.body.fail if @response.body.respond_to?(:fail)
155:       @backend.connection_finished(self)
156:     end

Protected Instance socket_address()

Returns IP address of peer as a string.

     # File lib/thin/connection.rb, line 192
192:       def socket_address
193:         Socket.unpack_sockaddr_in(get_peername)[1]
194:       end