Parent

Included Modules

Thin::Connection

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

Constants

CONTENT_LENGTH
TRANSFER_ENCODING
CHUNKED_REGEXP
AsyncResponse

This is a template async response. N.B. Can’t use string for body on 1.9

Attributes

app[RW]

Rack application (adapter) served by this connection.

backend[RW]

Backend to the server

request[RW]

Current request served by the connection

response[RW]

Next response sent through the connection

threaded[W]

Calling the application in a threaded allowing concurrent processing of requests.

Public Instance Methods

can_persist!() click to toggle source

Allows this connection to be persistent.

     # File lib/thin/connection.rb, line 167
167:     def can_persist!
168:       @can_persist = true
169:     end
can_persist?() click to toggle source

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

     # File lib/thin/connection.rb, line 172
172:     def can_persist?
173:       @can_persist
174:     end
close_request_response() click to toggle source
     # File lib/thin/connection.rb, line 136
136:     def close_request_response
137:       @request.async_close.succeed if @request.async_close
138:       @request.close  rescue nil
139:       @response.close rescue nil
140:     end
handle_error() click to toggle source

Logs catched exception and closes the connection.

     # File lib/thin/connection.rb, line 130
130:     def handle_error
131:       log "!! Unexpected error while processing request: #{$!.message}"
132:       log_error
133:       close_connection rescue nil
134:     end
persistent?() click to toggle source

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

     # File lib/thin/connection.rb, line 178
178:     def persistent?
179:       @can_persist && @response.persistent?
180:     end
post_init() click to toggle source

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
post_process(result) click to toggle source
     # File lib/thin/connection.rb, line 93
 93:     def post_process(result)
 94:       return unless result
 95:       result = result.to_a
 96:       
 97:       # Status code -1 indicates that we're going to respond later (async).
 98:       return if result.first == AsyncResponse.first
 99: 
100:       # Set the Content-Length header if possible
101:       set_content_length(result) if need_content_length?(result)
102:       
103:       @response.status, @response.headers, @response.body = *result
104: 
105:       log "!! Rack application returned nil body. Probably you wanted it to be an empty string?" if @response.body.nil?
106: 
107:       # Make the response persistent if requested by the client
108:       @response.persistent! if @request.persistent?
109: 
110:       # Send the response
111:       @response.each do |chunk|
112:         trace { chunk }
113:         send_data chunk
114:       end
115: 
116:     rescue Exception
117:       handle_error
118:     ensure
119:       # If the body is being deferred, then terminate afterward.
120:       if @response.body.respond_to?(:callback) && @response.body.respond_to?(:errback)
121:         @response.body.callback { terminate_request }
122:         @response.body.errback  { terminate_request }
123:       else
124:         # Don't terminate the response if we're going async.
125:         terminate_request unless result && result.first == AsyncResponse.first
126:       end
127:     end
pre_process() click to toggle source
    # 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:       if @backend.ssl?
71:         @request.env["rack.url_scheme"] = "https"
72:         
73:         if cert = get_peer_cert
74:           @request.env['rack.peer_cert'] = cert
75:         end
76:       end
77: 
78:       # When we're under a non-async framework like rails, we can still spawn
79:       # off async responses using the callback info, so there's little point
80:       # in removing this.
81:       response = AsyncResponse
82:       catch(:async) do
83:         # Process the request calling the Rack adapter
84:         response = @app.call(@request.env)
85:       end
86:       response
87:     rescue Exception
88:       handle_error
89:       terminate_request
90:       nil # Signal to post_process that the request could not be processed
91:     end
process() click to toggle source

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
receive_data(data) click to toggle source

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
remote_address() click to toggle source

IP Address of the remote client.

     # File lib/thin/connection.rb, line 190
190:     def remote_address
191:       socket_address
192:     rescue Exception
193:       log_error
194:       nil
195:     end
terminate_request() click to toggle source

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
146:     def terminate_request
147:       unless persistent?
148:         close_connection_after_writing rescue nil
149:         close_request_response
150:       else
151:         close_request_response
152:         # Prepare the connection for another request if the client
153:         # supports HTTP pipelining (persistent connection).
154:         post_init
155:       end
156:     end
threaded?() click to toggle source

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
185:     def threaded?
186:       @threaded || (@app.respond_to?(:deferred?) && @app.deferred?(@request.env))
187:     end
unbind() click to toggle source

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
160:     def unbind
161:       @request.async_close.succeed if @request.async_close
162:       @response.body.fail if @response.body.respond_to?(:fail)
163:       @backend.connection_finished(self)
164:     end

Protected Instance Methods

socket_address() click to toggle source

Returns IP address of peer as a string.

     # File lib/thin/connection.rb, line 200
200:       def socket_address
201:         Socket.unpack_sockaddr_in(get_peername)[1]
202:       end

Private Instance Methods

need_content_length?(result) click to toggle source
     # File lib/thin/connection.rb, line 205
205:       def need_content_length?(result)
206:         status, headers, body = result
207:         return false if status == 1
208:         return false if headers.has_key?(CONTENT_LENGTH)
209:         return false if (100..199).include?(status) || status == 204 || status == 304
210:         return false if headers.has_key?(TRANSFER_ENCODING) && headers[TRANSFER_ENCODING] =~ CHUNKED_REGEXP
211:         return false unless body.kind_of?(String) || body.kind_of?(Array)
212:         true
213:       end
set_content_length(result) click to toggle source
     # File lib/thin/connection.rb, line 215
215:       def set_content_length(result)
216:         headers, body = result[1..2]
217:         case body
218:         when String
219:           # See http://redmine.ruby-lang.org/issues/show/203
220:           headers[CONTENT_LENGTH] = (body.respond_to?(:bytesize) ? body.bytesize : body.size).to_s
221:         when Array
222:            bytes = 0
223:            body.each do |p|
224:              bytes += p.respond_to?(:bytesize) ? p.bytesize : p.size
225:            end
226:            headers[CONTENT_LENGTH] = bytes.to_s
227:         end
228:       end

Disabled; run with --debug to generate this.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.